54

2 つの色があり、ある色から別の色にすばやく切り替わるリアルタイム アニメーションを作成する必要があるとします。

もう一方の色に到達するまで 16 進数の色をインクリメントしようとしましたが、関係のない色がたくさん表示されたため、非常に悪いアニメーションになりました。

setColorFilter(color, colorfilter)イメージビューの色を変更するために使用しています。

HUE を変更すると、最高のビジュアル結果が得られますか? もしそうなら、どうすれば単色に変更できますか?

解決策:色相を再帰的にシフトすることで解決しました

private int hueChange(int c,int deg){
       float[] hsv = new float[3];       //array to store HSV values
       Color.colorToHSV(c,hsv); //get original HSV values of pixel
       hsv[0]=hsv[0]+deg;                //add the shift to the HUE of HSV array
       hsv[0]=hsv[0]%360;                //confines hue to values:[0,360]
       return Color.HSVToColor(Color.alpha(c),hsv);
    }
4

12 に答える 12

77

@zed と @Phil の回答を組み合わせると、ValueAnimator.

final float[] from = new float[3],
              to =   new float[3];

Color.colorToHSV(Color.parseColor("#FFFFFFFF"), from);   // from white
Color.colorToHSV(Color.parseColor("#FFFF0000"), to);     // to red

ValueAnimator anim = ValueAnimator.ofFloat(0, 1);   // animate from 0 to 1
anim.setDuration(300);                              // for 300 ms

final float[] hsv  = new float[3];                  // transition color
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){
    @Override public void onAnimationUpdate(ValueAnimator animation) {
        // Transition along each axis of HSV (hue, saturation, value)
        hsv[0] = from[0] + (to[0] - from[0])*animation.getAnimatedFraction();
        hsv[1] = from[1] + (to[1] - from[1])*animation.getAnimatedFraction();
        hsv[2] = from[2] + (to[2] - from[2])*animation.getAnimatedFraction();

        view.setBackgroundColor(Color.HSVToColor(hsv));
    }
});

anim.start();                                        

HSV は、色のプロパティを適切に分離し、単一の軸全体でスムーズな遷移を可能にする円筒座標で色を記述するため、HSV は Android のデフォルトの色空間よりも優れた遷移を提供します。下の画像から、H、S、または V 方向に沿って移動すると、色が連続的に変化することがわかります。

ここに画像の説明を入力

于 2014-07-08T21:34:43.713 に答える
20

次を使用できますValueAnimator

//animate from your current color to red
ValueAnimator anim = ValueAnimator.ofInt(view.getBackgroundColor(), Color.parseColor("#FF0000"));
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        view.setBackgroundColor(animation.getAnimatedValue());
    }
});

anim.start();

を呼び出す前に期間やその他のパラメータを設定することもできますanim.start()。例えば:

anim.setDuration(400);

アニメーションの長さを 400 ミリ秒に設定します。


最後に、はHoneycombValueAnimatorから利用できることに注意してください。したがって、古い SDK をサポートしている場合は、NineOldAndroidsを使用できます。

于 2013-08-13T18:59:02.723 に答える
11

他の答えは、非常に異なる色を移行するときに奇妙な効果をもたらしました。黄色から灰色まで、アニメーションのある時点で緑色に達します。

私にとって最も効果的だったのは、次のスニペットでした。これにより、奇妙な色が間に現れることなく、非常にスムーズな移行が作成されました.

private void changeViewColor(View view) {
    // Load initial and final colors.
    final int initialColor = getResources().getColor(R.color.some_color);
    final int finalColor = getResources().getColor(R.color.another_color);

    ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            // Use animation position to blend colors.
            float position = animation.getAnimatedFraction();
            int blended = blendColors(initialColor, finalColor, position);

            // Apply blended color to the view.
            view.setBackgroundColor(blended);
        }
    });

    anim.setDuration(500).start();
}

private int blendColors(int from, int to, float ratio) {
    final float inverseRatio = 1f - ratio;

    final float r = Color.red(to) * ratio + Color.red(from) * inverseRatio;
    final float g = Color.green(to) * ratio + Color.green(from) * inverseRatio;
    final float b = Color.blue(to) * ratio + Color.blue(from) * inverseRatio;

    return Color.rgb((int) r, (int) g, (int) b);
}
于 2015-01-30T15:59:53.467 に答える
8

TransitionDrawable を使用できます

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

drawable フォルダーに xml ファイルを作成すると、次のように記述できます。

<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/end_color" />
    <item android:drawable="@drawable/start_color" />
</transition>

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

于 2014-09-04T11:42:09.737 に答える
4

次のスニペットは私にとって完璧に機能しました。ValueAnimator.ofArgb() を使用することを考えましたが、それには最低 api 21 が必要です。代わりに、以下は api 11 以降で動作します。滑らかな色変化を実現。

ArgbEvaluator evaluator = new ArgbEvaluator();
ValueAnimator animator = new ValueAnimator();
animator.setIntValues(Color.parseColor("#FFFFFF"), Color.parseColor("#000000"));
animator.setEvaluator(evaluator);
animator.setDuration(1000);
//animator.setRepeatCount(ValueAnimator.INFINITE);
//animator.setRepeatMode(ValueAnimator.REVERSE);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            color = (int) animation.getAnimatedValue();
            //postInvalidate(); if you are animating a canvas
            //View.setBackgroundColor(color); another exampleof where to use
        }
    });
animator.start();
于 2015-10-29T01:29:47.583 に答える
3

解決策:色相を再帰的にシフトすることで解決しました

private int hueChange(int c,int deg){
       float[] hsv = new float[3];       //array to store HSV values
       Color.colorToHSV(c,hsv); //get original HSV values of pixel
       hsv[0]=hsv[0]+deg;                //add the shift to the HUE of HSV array
       hsv[0]=hsv[0]%360;                //confines hue to values:[0,360]
       return Color.HSVToColor(Color.alpha(c),hsv);
    }
于 2014-05-07T19:20:38.867 に答える
0

まず、HSV に関するすばらしい回答とデータを提供してくれた @bcorso に感謝します。

提案されたアルゴリズムをしばらく使用していたとき、ある色から別の色に色が変化し、その過程で無関係な色に触れるという事実に少しイライラしました。そこで、実際の 3D 座標を使用してそのような補間を行う、愚かで単純な独自のアルゴリズムを最終的に実装しました。

https://github.com/konmik/animated-color

于 2015-10-19T21:07:22.990 に答える