android - 我的 android 动画时间有什么问题?

标签 android android-layout animation layout android-animation

我有以下开关按钮(我是为 Android 2.3+ 创建的,所以不能使用 native 开关)。

enter image description here

使用以下 XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/settingsSwitchMainLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="true" >

    <ImageView
        android:id="@+id/switch_bg2"
        android:layout_width="90dp"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerInParent="true"
        android:layout_centerVertical="true"
        android:src="@drawable/switch_bg_off" />

    <RelativeLayout
        android:id="@+id/switch_handle"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentRight="true"
        android:layout_marginTop="7dp"
        android:background="@drawable/switch_handle"
        android:padding="0dp" >

        <ImageView
            android:id="@+id/switch_v"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="17dp"
            android:layout_marginTop="14dp"
            android:src="@drawable/switch_v"
            android:visibility="visible" />
    </RelativeLayout>

</RelativeLayout>

以及以下代码:

    public class SettingsSwitchView extends RelativeLayout {

        private enum SwitchModes {
            CHECKED, UNCHECKED
        }

        private static final int FULL_DURATION = 18000;

        private ImageView mSwitchBg2;
        private RelativeLayout mSwitchHandle;
        private ImageView mSwitchV;
        private NinePatchDrawable mBgTransition;

        private boolean isChecked;

        public SettingsSwitchView(Context context, AttributeSet attrs) {
            super(context, attrs);
            inflater = LayoutInflater.from(context);
            inflater.inflate(R.layout.settings_switch, this);
            initMemebers();

            isChecked = true; // read from config file
            setOnClickListeners();
        }

        private void setOnClickListeners() {
            mSwitchBg2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    isChecked = !isChecked;
                    SwitchModes switchMode = (isChecked)? SwitchModes.CHECKED : SwitchModes.UNCHECKED;
                    anim_first(switchMode);
                }
            });
        }


        private void anim_first(SwitchModes mode)
        {
            AnimationSet bgAnimation = new AnimationSet(true);

            //bg fade out
            AlphaAnimation alpha_bg_0_50 = getBgAlphafirst(mode);

            //fade_V
            AlphaAnimation alpha_V_0_100 = getVAlphafirst(mode);

            mSwitchV.startAnimation(alpha_V_0_100);

            //slide 
            Animation slide_box_0_100 = getSlideFirst(mode);

            mSwitchHandle.startAnimation(slide_box_0_100);


            //bg fade in
            AlphaAnimation alpha_bg_50_100 = getBgAlphaSecond();
            bgAnimation.addAnimation(alpha_bg_0_50);
            bgAnimation.addAnimation(alpha_bg_50_100);
            mSwitchBg2.startAnimation(bgAnimation);

            //extra slide, stretch
            mSwitchBg2.startAnimation(getExtraScale(mode));
            mSwitchHandle.startAnimation(getExtraSlide(mode));
        }

public class SettingsSwitchView extends RelativeLayout {

    private enum SwitchModes {
        CHECKED, UNCHECKED
    }

    private static final int FULL_DURATION = 18000;

    private static final int TRANSITION_DURATION = 180;
    private static final int ALPHA_DURATION = 180;
    //private static final int BG_TRANSITION_TIME = 40;
    private LayoutInflater inflater;

    //private RelativeLayout mSwitchBg;
    private ImageView mSwitchBg2;
    private RelativeLayout mSwitchHandle;
    private ImageView mSwitchV;
    // private TransitionDrawable mBgTransition;
    private NinePatchDrawable mBgTransition;

    private boolean isChecked;

    public SettingsSwitchView(Context context, AttributeSet attrs) {
        super(context, attrs);
        inflater = LayoutInflater.from(context);
        inflater.inflate(R.layout.settings_switch, this);
        initMemebers();

        isChecked = true; // read from config file
        setOnClickListeners();
    }

    private void setOnClickListeners() {
        mSwitchBg2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                isChecked = !isChecked;
                SwitchModes switchMode = (isChecked)? SwitchModes.CHECKED : SwitchModes.UNCHECKED;
                anim_first(switchMode);
            }
        });
    }


    private void anim_first(SwitchModes mode)
    {
        AnimationSet bgAnimation = new AnimationSet(true);

        //bg fade out
        AlphaAnimation alpha_bg_0_50 = getBgAlphafirst(mode);

        //fade_V
        AlphaAnimation alpha_V_0_100 = getVAlphafirst(mode);

        mSwitchV.startAnimation(alpha_V_0_100);

        //slide 
        Animation slide_box_0_100 = getSlideFirst(mode);

        mSwitchHandle.startAnimation(slide_box_0_100);


        //bg fade in
        AlphaAnimation alpha_bg_50_100 = getBgAlphaSecond();
        bgAnimation.addAnimation(alpha_bg_0_50);
        bgAnimation.addAnimation(alpha_bg_50_100);
        mSwitchBg2.startAnimation(bgAnimation);

        //extra slide, stretch
        mSwitchBg2.startAnimation(getExtraScale(mode));
        mSwitchHandle.startAnimation(getExtraSlide(mode));
    }

    private TranslateAnimation getExtraSlide(SwitchModes mode) {

        final TranslateAnimation translate;

        switch (mode) {
        case CHECKED: {
            translate = new TranslateAnimation(Animation.RELATIVE_TO_SELF, -15, Animation.RELATIVE_TO_SELF, -5, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
            break;
        }
        default:
        case UNCHECKED: {
            translate =  new TranslateAnimation(Animation.RELATIVE_TO_SELF, -60, Animation.RELATIVE_TO_SELF, -70, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
            break;
        }
        }

        translate.setDuration(FULL_DURATION/4);
        translate.setStartOffset(FULL_DURATION);

        return translate;
    }


    private ScaleAnimation getExtraScale(SwitchModes mode) {
        final ScaleAnimation scaleAnimation;

        switch (mode) {
        case CHECKED: {
            scaleAnimation = new ScaleAnimation(1, (float)1.1, 1, 1, Animation.RELATIVE_TO_SELF, (float)0.1, Animation.RELATIVE_TO_SELF, (float)0.5);
            break;
        }
        default:
        case UNCHECKED: {
            scaleAnimation = new ScaleAnimation(1, (float)1.1, 1, 1, Animation.RELATIVE_TO_SELF, (float)0.9, Animation.RELATIVE_TO_SELF, (float)0.5);
            break;
        }
        }

        scaleAnimation.setDuration(FULL_DURATION/4);
        scaleAnimation.setStartOffset(FULL_DURATION);

        return scaleAnimation;
    }


    private AlphaAnimation getVAlphafirst(SwitchModes mode) {
        AlphaAnimation alpha;
        switch (mode) {
        case CHECKED: {
            mSwitchV.setVisibility(View.VISIBLE);
            alpha = new AlphaAnimation(0, 1);
            break;
        }
        default:
        case UNCHECKED: {
            mSwitchV.setVisibility(View.GONE);
            alpha = new AlphaAnimation(1, 0);
            break;
        }
        }
        alpha.setDuration(FULL_DURATION);
        alpha.setFillAfter(true);
        return alpha;
    }

    private AlphaAnimation getBgAlphafirst(SwitchModes mode) {
        AlphaAnimation alpha;
        alpha = new AlphaAnimation(1, (float) 0.5);
        alpha.setDuration(FULL_DURATION/2);

        switch (mode) {
        case CHECKED: {
            mSwitchBg2.setImageDrawable(getResources().getDrawable(R.drawable.switch_bg_on));
            break;
        }
        case UNCHECKED: {
            mSwitchBg2.setImageDrawable(getResources().getDrawable(R.drawable.switch_bg_off));
            break;
        }
        }
        return alpha;

    }

    private AlphaAnimation getBgAlphaSecond() {
        AlphaAnimation alpha;
        alpha = new AlphaAnimation((float) 0.5, 1);
        alpha.setDuration(FULL_DURATION/2);
        alpha.setStartOffset(FULL_DURATION/2);
        return alpha;
    }

    private Animation getSlideFirst(SwitchModes mode) {
        Animation aniamtion;
        switch (mode) {
        case CHECKED: {
            aniamtion = android.view.animation.AnimationUtils.loadAnimation(
                    AppService.getAppContext(), com.myApp.R.anim.slide_to_right);
            break;
        }
        default:
        case UNCHECKED: {
            aniamtion = android.view.animation.AnimationUtils.loadAnimation(
                    AppService.getAppContext(), com.myApp.R.anim.slide_to_left);
            break;
        }
        }

        aniamtion.setDuration(FULL_DURATION);
        aniamtion.setInterpolator(new AccelerateInterpolator());
        aniamtion.setFillAfter(true);
        return aniamtion;
    }

    private void initMemebers() {
        //mSwitchBg = (RelativeLayout) findViewById(R.id.switch_bg);
        mSwitchBg2 = (ImageView) findViewById(R.id.switch_bg2);

        mSwitchHandle = (RelativeLayout) findViewById(R.id.switch_handle);
        mSwitchV = (ImageView) findViewById(R.id.switch_v);
    }
}

我正在使用 android 动画来创建这个动画:

1) bg 颜色将从“关闭”转换为“打开”(一个淡入,另一个淡出)

2) 同时白框会从一侧移动到另一侧

3) 在这个时间的一半时,v 符号将完全淡出

然后

4) 白框会稍微拉长背景,然后回到原来的位置。

5) 同时,背景会被拉伸(stretch)并恢复到原来的大小。

slide_to_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set
     xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_interpolator">
    <translate
        android:fromXDelta="-15%"
        android:toXDelta="-60%">

    </translate>
</set>

但在实时中,动画与我想要的完全不同。

1) 第一次点击后白框消失了——我认为 bg 的变化覆盖了它上面的所有内容。

2) 下一步点击背景颜色立即改变,无淡入淡出。

有人知道我做错了什么吗?

最佳答案

我建议您使用 AnimationListener 来等待一个动画完成,然后再开始下一个动画,如果您想混合使用它们,请使用 http://nineoldandroids.com对于复杂的动画。

九老机器人是 Android 3.0 中引入的属性动画的向后兼容版本。

即使您设法使具有多个偏移量的多个动画在您的手机上运行,​​也不意味着它会在所有手机上运行。

我通过艰难的方式了解到,在我的应用程序经过完善并且在我的手机上一切正常后,我查看了其他一些(甚至是 4.x)手机,我不得不重构所有动画。

关于android - 我的 android 动画时间有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19737539/

相关文章:

android - 交叉编译arm64

android - 两个或多个组件作为一个 "big"组件

android - 查看通货膨胀和自定义 View

c# - 从代码隐藏中在 WPF 中移动 Canvas 上的矩形

html - 显示子元素时调整元素大小的过渡

android - 在 DatePickerDialog Android 中禁用今天日期之前的日期?

java - F-Droid.com 上的 R.java 文件

Android 线性布局重量和软键盘问题

android - 如何从屏幕底部到顶部为 ConstraintLayout 设置动画?

java - 如何全局获取Android中的鼠标位置