通过动画过渡动态更改背景颜色

时间:2013-09-15 23:40:56

标签: java android animation random colors

我正在尝试生成随机颜色并将其设置为背景,速度为3秒。我创建了一个thread来处理这个变化,现在我想在颜色变化之间添加一个过渡,使其融合得很好。

作为参考,请查看this app

编辑: 我已尝试在循环中使用ObjectAnimatorArgbEvaluator,并且过渡时间为3秒,但屏幕会以类似频闪的方式闪烁,这会让您头疼。除此之外,颜色变化很好,其他一切都很完美。有人可以运行这个,看看会出现什么问题吗?

public class Main extends Activity {

public int color1, color2, red1, red2, blue1, blue2, green1, green2;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);


    new Thread() {
        public void run() {
            while(true) {
                try {
                    Thread.sleep(3000); // I've also tried 1000 and 4000, same issue.
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Main.this.runOnUiThread(new Runnable() {
                    public void run() {

                    //generate color 1
                        red1 = (int)(Math.random() * 128 + 127);
                        green1 = (int)(Math.random() * 128 + 127);
                        blue1 = (int)(Math.random() * 128 + 127);
                        color1 = 0xff << 24 | (red1 << 16) |
                                (green1 << 8) | blue1;


                    //generate color 2

                        red2 = (int)(Math.random() * 128 + 127);
                        green2 = (int)(Math.random() * 128 + 127);
                        blue2 = (int)(Math.random() * 128 + 127);
                        color2 = 0xff << 24 | (red2 << 16) |
                                (green2 << 8) | blue2;

                    //start animation
                        View v = findViewById(R.id.view);
                        ObjectAnimator anim = ObjectAnimator.ofInt(v, "backgroundColor", color1, color2);


                        anim.setEvaluator(new ArgbEvaluator());
                        anim.setRepeatCount(ValueAnimator.INFINITE);
                        anim.setRepeatMode(ValueAnimator.REVERSE);
                        anim.setDuration(3000);
                        anim.start();

                    }
                });
            }
        }
    }.start();
}

}

编辑:我把它缩小了,发现“.setRepeatMode”导致了这个问题。我还没有修复。通过将“反向”更改为其他内容(无限或其他提供的选项),可以防止动画发生。知道我能做些什么来解决这个问题吗?

另外,有没有人知道更好的方式来产生更鲜艳的色彩?我所看到的一切都已经过时了。

3 个答案:

答案 0 :(得分:5)

除了一件事,你正在做所有事情:每隔3秒,你就会随机生成 2 颜色。所以,这就是发生的事情:

  

第一次迭代

     生成

color1

     生成

color2

     

视图的背景设置为color1。然后背景发生变化   从color1到color2。

     

//好的

     

第二次迭代

     

有一个新的color1

     

有一个新的颜色2

     

视图的背景设置为 new color1 。立即改变的原因   频闪灯光效果。然后背景从新的变化   color1到new color2。

你应该怎么做才能解决这个问题:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);

    // Generate color1 before starting the thread
    red1 = (int)(Math.random() * 128 + 127);
    green1 = (int)(Math.random() * 128 + 127);
    blue1 = (int)(Math.random() * 128 + 127);
    color1 = 0xff << 24 | (red1 << 16) |
                          (green1 << 8) | blue1;


    new Thread() {
        public void run() {
            while(true) {
                try {
                    Thread.sleep(3000); 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Main.this.runOnUiThread(new Runnable() {
                    public void run() {

                    //generate color 2

                        red2 = (int)(Math.random() * 128 + 127);
                        green2 = (int)(Math.random() * 128 + 127);
                        blue2 = (int)(Math.random() * 128 + 127);
                        color2 = 0xff << 24 | (red2 << 16) |
                                (green2 << 8) | blue2;

                    //start animation
                        View v = findViewById(R.id.view);
                        ObjectAnimator anim = ObjectAnimator.ofInt(v, "backgroundColor", color1, color2);


                        anim.setEvaluator(new ArgbEvaluator());
                        anim.setRepeatCount(ValueAnimator.INFINITE);
                        anim.setRepeatMode(ValueAnimator.REVERSE);
                        anim.setDuration(3000);
                        anim.start();

                        // Now set color1 to color2
                        // This way, the background will go from
                        // the previous color to the next color
                        // smoothly
                        color1 = color2;

                    }
                });
            }
        }
    }.start();
}

因此,从第二次迭代开始,起始颜色应与上一次迭代的结束颜色相同。仅初始化/生成color1一次:在启动线程之前。在anim.start()之后,添加:

color1 = color2;

另请注意,您每隔 3秒创建一个新的ObjectAnimator

ObjectAnimator anim = ObjectAnimator.ofInt(v, "backgroundColor", color1, color2);

因此,以下陈述无效:

anim.setRepeatCount(ValueAnimator.INFINITE);
anim.setRepeatMode(ValueAnimator.REVERSE); 

以下是我的建议:

public class Main extends Activity {

    public int color1, color2, red1, red2, blue1, blue2, green1, green2;

    View v;

    ObjectAnimator anim;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);

        // White or whatever color background R.id.view
        // has at the beginning
        color1 = 0xffffffff;

        v = findViewById(R.id.llMain);

        // We haven't initialized color2 yet. Will set this later
        anim = ObjectAnimator.ofInt(v, "backgroundColor", color1);

        anim.setEvaluator(new ArgbEvaluator());

        anim.setDuration(3000);


        new Thread() {
            public void run() {
                while(true) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Main.this.runOnUiThread(new Runnable() {
                        public void run() {

                            //generate color 2

                            red2 = (int)(Math.random() * 128 + 127);
                            green2 = (int)(Math.random() * 128 + 127);
                            blue2 = (int)(Math.random() * 128 + 127);
                            color2 = 0xff << 24 | (red2 << 16) |
                                    (green2 << 8) | blue2;

                            // Update the color values
                            anim.setIntValues(color1, color2);

                            anim.start();

                            // Order the colors
                            color1 = color2;

                        }
                    });
                }
            }
        }.start();
    }
}

这样,您只需创建一次ObjectAnimator对象,并每隔3秒更新一次颜色值。

答案 1 :(得分:2)

如何使用ObjectAnimator w / ArgbEvaluator。使用ObjectAnimator,如果对象在camel情况下具有正确的setter方法(以set()的形式),则可以轻松地为任何属性设置动画。在您的情况下,View有setBackgroundColor,因此您可以尝试:

View v = findViewById(R.id.mask2);
ObjectAnimator anim = ObjectAnimator.ofInt(v, "backgroundColor", Color.RED, Color.BLUE);
anim.setDuration(3000);
anim.setEvaluator(new ArgbEvaluator());
anim.setRepeatCount(ValueAnimator.INFINITE);
anim.setRepeatMode(ValueAnimator.REVERSE);
anim.start();

更一般的&amp;有关物业动画的详细说明:

  

http://developer.android.com/guide/topics/graphics/prop-animation.html#object-animator

不幸的是,这个新api仅支持API11 +,因此如果您担心兼容性问题,可以尝试使用JakeWharton编写的NineOldAndroids库。

答案 2 :(得分:1)

另一种替代方法如何改变背景的颜色;

    ColorDrawable[] color = { new ColorDrawable(Color.RED), new ColorDrawable(Color.WHITE) };
    TransitionDrawable trans = new TransitionDrawable(color);
    view.setBackgroundDrawable(trans);
    trans.startTransition(3000);

这种方法也有像trans.reverse Transition(duration)这样的方法。