1

次のスイッチ ボタンがあります (Android 2.3 以降用に作成したため、ネイティブ スイッチは使用できません)。

ここに画像の説明を入力

次の 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) 背景色は「オフ」から「オン」に変換されます (1 つはフェードインし、もう 1 つはフェードアウトします)。

2) 同時に、白いボックスが一方の側から他方の側に移動します

3) この時間の半分で、v サインは完全にフェードアウトします。

それで

4) 白いボックスは背景を少し引き伸ばし、元の位置に戻ります。

5) 同時に背景が引き伸ばされ、元のサイズに戻ります。

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) 次に bg の色を一度にクリックすると、フェードインとフェードアウトはありません。

誰かが私が間違っていることを知っていますか?

4

1 に答える 1

2

AnimationListener を使用して、1 つのアニメーションが終了するのを待ってから次のアニメーションを開始することをお勧めします。それらを混ぜ合わせたい場合は、複雑なアニメーションにはhttp://nineoldandroids.comを使用してください。

Nine Old Androids は、Android 3.0 で導入されたプロパティ アニメーションの下位互換バージョンです。

複数のオフセットを使用して複数のアニメーションを携帯電話で動作させることができたとしても、すべての携帯電話で動作するとは限りません。

アプリが洗練され、携帯電話ですべてが正常に機能した後、他の (4.x も含む) 携帯電話を見て、すべてのアニメーションをリファクタリングする必要がありました。

于 2013-11-02T15:54:59.893 に答える