web-dev-qa-db-ja.com

Androidでビューの背景色の変化をアニメートする

Androidでビューの背景色の変化をどのようにアニメートしますか?

例えば:

背景色が赤のビューがあります。ビューの背景色が青に変わります。どのようにして色を滑らかに変化させることができますか?

これがビューではできない場合は、代わりの方法があります。

301
hpique

私はこの問題に対する(かなり良い)解決策を考え出すことになった!

これを実現するには、 TransitionDrawable を使用できます。たとえば、drawableフォルダ内のXMLファイルでは、次のように書くことができます。

<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <!-- The drawables used here can be solid colors, gradients, shapes, images, etc. -->
    <item Android:drawable="@drawable/original_state" />
    <item Android:drawable="@drawable/new_state" />
</transition>

次に、実際のビューのXMLでは、このTransitionDrawableをAndroid:background属性で参照します。

この時点で、次のようにしてコード内でコードの移行を開始できます。

TransitionDrawable transition = (TransitionDrawable) viewObj.getBackground();
transition.startTransition(transitionTime);

あるいは以下のように呼び出して遷移を逆に実行します。

transition.reverseTransition(transitionTime);

Property Animation APIを使用した別の解決策については、 Roman's answer を参照してください。この回答が最初に投稿された時点では利用できませんでした。

345
idolize

カラーアニメーションにはnew Property Animation Api を使用できます。

int colorFrom = getResources().getColor(R.color.red);
int colorTo = getResources().getColor(R.color.blue);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(250); // milliseconds
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animator) {
        textView.setBackgroundColor((int) animator.getAnimatedValue());
    }

});
colorAnimation.start();

Android 2.xとの後方互換性のために Nine Old Androids library Jake Whartonからを使用してください。

getColorメソッドはAndroid Mでは推奨されていなかったので、2つの選択肢があります。

  • サポートライブラリを使用する場合は、getColorの呼び出しを次のように置き換える必要があります。

    ContextCompat.getColor(this, R.color.red);
    
  • サポートライブラリを使用しない場合は、getColorの呼び出しを次のように置き換える必要があります。

    getColor(R.color.red);
    
460
Roman Minenok

ビューの背景色の取得方法とターゲット色の取得方法に応じて、これを行う方法がいくつかあります。

最初の2つは Android Property Animation フレームワークを使います。

次の場合は Object Animator を使用してください。

  • ビューの背景色は、xmlファイルのargb値として定義されています。
  • あなたのビューは以前にその色がview.setBackgroundColor()によって設定されていました
  • あなたのビューの背景色はdrawableで定義されています。DOES NOTはストロークやコーナーの半径などの追加のプロパティを定義します。
  • ビューの背景色はドロウアブルで定義されており、ストロークやコーナーの半径などの余分なプロパティを削除する場合は、余分なプロパティを削除してもアニメーション化されないことに注意してください。

オブジェクトアニメータは、定義されたdrawableがColorDrawableのインスタンスでない限り、定義されたdrawableを置き換えるview.setBackgroundColorを呼び出すことによって機能します。これは、ストロークや角のようなドロウアブルからの余分な背景プロパティが削除されることを意味します。

次の場合は、 Value Animator を使用してください。

  • ビューの背景色は、ストロークやコーナーの半径などのプロパティも設定するdrawableで定義されており、実行中に決定された新しい色に変更する必要があります。

次の場合は、 Transition drawable を使用してください。

  • 展開前に定義されている2つのドロアブルを切り替える必要があります。

DrawerLayoutを開いている間に実行できないトランジションドロアブルでパフォーマンス上の問題がいくつかありました。予期しない吃音が発生した場合は、同じバグが発生する可能性があります。

StateLists drawable または LayerLists drawable を使用する場合は、Value Animatorの例を変更する必要があります。そうしないと、final GradientDrawable background = (GradientDrawable) view.getBackground();行でクラッシュします。

Object Animator

ビュー定義:

<View
    Android:background="#FFFF0000"
    Android:layout_width="50dp"
    Android:layout_height="50dp"/>

このようにObjectAnimatorを作成して使用します。

final ObjectAnimator backgroundColorAnimator = ObjectAnimator.ofObject(view,
                                                                       "backgroundColor",
                                                                       new ArgbEvaluator(),
                                                                       0xFFFFFFFF,
                                                                       0xff78c5f9);
backgroundColorAnimator.setDuration(300);
backgroundColorAnimator.start();

XMightのようにAnimatorInflaterを使用してxmlからアニメーション定義をロードすることもできます Android objectAnimator animate backgroundColor of Layout

Value Animator

ビュー定義:

<View
    Android:background="@drawable/example"
    Android:layout_width="50dp"
    Android:layout_height="50dp"/>

描画可能な定義:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <solid Android:color="#FFFFFF"/>
    <stroke
        Android:color="#edf0f6"
        Android:width="1dp"/>
    <corners Android:radius="3dp"/>

</shape>

このようなValueAnimatorを作成して使用します。

final ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(),
                                                           0xFFFFFFFF,
                                                           0xff78c5f9);

final GradientDrawable background = (GradientDrawable) view.getBackground();
currentAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(final ValueAnimator animator) {
        background.setColor((Integer) animator.getAnimatedValue());
    }

});
currentAnimation.setDuration(300);
currentAnimation.start();

遷移描画可能

ビュー定義:

<View
    Android:background="@drawable/example"
    Android:layout_width="50dp"
    Android:layout_height="50dp"/>

描画可能な定義:

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item>
        <shape>
            <solid Android:color="#FFFFFF"/>
            <stroke
                Android:color="#edf0f6"
                Android:width="1dp"/>
            <corners Android:radius="3dp"/>
        </shape>
    </item>

    <item>
        <shape>
            <solid Android:color="#78c5f9"/>
            <stroke
                Android:color="#68aff4"
                Android:width="1dp"/>
            <corners Android:radius="3dp"/>
        </shape>
    </item>
</transition>

このようにTransitionDrawableを使用します。

final TransitionDrawable background = (TransitionDrawable) view.getBackground();
background.startTransition(300);

アニメーションインスタンスで.reverse()を呼び出すことでアニメーションを元に戻すことができます。

アニメーションを実行する方法は他にもありますが、これら3つがおそらく最も一般的です。私は通常ValueAnimatorを使います。

127
Mattias

あなたはオブジェクトのアニメーターを作ることができます。例えば、私はtargetViewを持っています、そして私はあなたの背景色を変えたいです:

int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
    .setDuration(duration)
    .start();
49
ademar111190

あなたがこのようなカラーアニメーションが欲しいならば、

Enter image description here

このコードはあなたを助けます:

ValueAnimator anim = ValueAnimator.ofFloat(0, 1);   
anim.setDuration(2000);

float[] hsv;
int runColor;
int hue = 0;
hsv = new float[3]; // Transition color
hsv[1] = 1;
hsv[2] = 1;
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {

        hsv[0] = 360 * animation.getAnimatedFraction();

        runColor = Color.HSVToColor(hsv);
        yourView.setBackgroundColor(runColor);
    }
});

anim.setRepeatCount(Animation.INFINITE);

anim.start();
19
RBK

これを実現するもう1つの簡単な方法は、AlphaAnimationを使用してフェードを実行することです。

  1. ビューをViewGroupにする
  2. インデックス0の子ビューを、match_parentレイアウト寸法で追加します。
  3. あなたの子供にコンテナと同じ背景を与えます
  4. 目的の色にコンテナの背景に変更
  5. AlphaAnimationを使って子をフェードアウトさせます。
  6. アニメーションが完了したら子を削除する(AnimationListenerを使用)
11
Stephane JAIS

最善の方法はValueAnimatorColorUtils.blendARGBを使うことです

 ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
 valueAnimator.setDuration(325);
 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {

              float fractionAnim = (float) valueAnimator.getAnimatedValue();

              view.setColorBackground(ColorUtils.blendARGB(Color.parseColor("#FFFFFF")
                                    , Color.parseColor("#000000")
                                    , fractionAnim));
        }
});
valueAnimator.start();
9
Rasoul Miri

これは、背景を変更するために基本アクティビティで使用する方法です。私はコードで生成されたGradientDrawablesを使っていますが、それに合わせて調整することもできます。

    protected void setPageBackground(View root, int type){
        if (root!=null) {
            Drawable currentBG = root.getBackground();
            //add your own logic here to determine the newBG 
            Drawable newBG = Utils.createGradientDrawable(type); 
            if (currentBG==null) {
                if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){
                    root.setBackgroundDrawable(newBG);
                }else{
                    root.setBackground(newBG);
                }
            }else{
                TransitionDrawable transitionDrawable = new TransitionDrawable(new Drawable[]{currentBG, newBG});
                transitionDrawable.setCrossFadeEnabled(true);
                if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){
                     root.setBackgroundDrawable(transitionDrawable);
                }else{
                    root.setBackground(transitionDrawable);
                }
                transitionDrawable.startTransition(400);
            }
        }
    }

pdate:私が見つけた同じ問題に遭遇した場合、何らかの理由でsetCrossFadeEnabled(true)を使ったAndroid <4.3では、@Romanを使った<4.3では純色に切り替える必要がありました上記のMinenok ValueAnimatorメソッド。

9
scottyab

答えはいろいろな方法で与えられます。 ValueAnimatorofArgb(startColor,endColor)を使用することもできます。

aPI> 21の場合:

int cyanColorBg = ContextCompat.getColor(this,R.color.cyan_bg);
int purpleColorBg = ContextCompat.getColor(this,R.color.purple_bg);

ValueAnimator valueAnimator = ValueAnimator.ofArgb(cyanColorBg,purpleColorBg);
        valueAnimator.setDuration(500);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator valueAnimator) {
                   relativeLayout.setBackgroundColor((Integer)valueAnimator.getAnimatedValue());
              }
        });
        valueAnimator.start();
5
Palak Darji

フォルダアニメータresフォルダに追加します。 (名前はアニメーターにする必要があります)。アニメーターリソースファイルを追加します。例えば、res/animator/fade.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <objectAnimator
        Android:propertyName="backgroundColor"
        Android:duration="1000"
        Android:valueFrom="#000000"
        Android:valueTo="#FFFFFF"
        Android:startOffset="0"
        Android:repeatCount="-1"
        Android:repeatMode="reverse" />
</set>

Activity Javaファイル内で、これを呼び出します。

View v = getWindow().getDecorView().findViewById(Android.R.id.content);
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.fade);
set.setTarget(v);
set.start();
4
canbax

これを可能にするNice関数があります。

public static void animateBetweenColors(final View viewToAnimateItBackground, final int colorFrom, final int colorTo,
        final int durationInMs) {
    final ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
    colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
        ColorDrawable colorDrawable = new ColorDrawable(colorFrom);

        @Override
        public void onAnimationUpdate(final ValueAnimator animator) {
            colorDrawable.setColor((Integer) animator.getAnimatedValue());
            viewToAnimateItBackground.setBackgroundDrawable(colorDrawable);
        }
    });
    if (durationInMs >= 0)
        colorAnimation.setDuration(durationInMs);
    colorAnimation.start();
}
4

私は、AndroidのソースコードでArgbEvaluatorが使用している実装が、色の遷移に最も適していることを発見しました。 HSVを使用する場合、2色によっては、移行が多すぎる色相を飛び越えていました。しかし、この方法は違います。

単純にアニメートしようとしている場合は、推奨されるようにArgbEvaluatorValueAnimatorと一緒に使用します ここ

ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animator) {
        view.setBackgroundColor((int) animator.getAnimatedValue());
    }

});
colorAnimation.start();

しかし、あなたが私のようなもので、ユーザーのジェスチャーや入力から渡される他の値と移行を結び付けたいのであれば、ValueAnimatorはあまり役に立ちません(あなたがAPI 22以降をターゲットにしているのでなければ、 ValueAnimator.setCurrentFraction() メソッド) API 22以下でターゲティングする場合は、次に示すように、 ArgbEvaluator source code にあるコードを独自のメソッドにラップします。

public static int interpolateColor(float fraction, int startValue, int endValue) {
    int startA = (startValue >> 24) & 0xff;
    int startR = (startValue >> 16) & 0xff;
    int startG = (startValue >> 8) & 0xff;
    int startB = startValue & 0xff;
    int endA = (endValue >> 24) & 0xff;
    int endR = (endValue >> 16) & 0xff;
    int endG = (endValue >> 8) & 0xff;
    int endB = endValue & 0xff;
    return ((startA + (int) (fraction * (endA - startA))) << 24) |
            ((startR + (int) (fraction * (endR - startR))) << 16) |
            ((startG + (int) (fraction * (endG - startG))) << 8) |
            ((startB + (int) (fraction * (endB - startB))));
}

そしてあなたが望むならそれを使ってください。

2
fahmy