0

我正在尝试生成随机颜色并将其设置为 3 秒的背景。我已经创建了一个thread可以处理这种变化的方法,现在我想在颜色变化之间添加一个过渡以使其很好地融合。

作为参考,看看这个应用程序

编辑:我尝试过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”导致了问题。我仍然没有修复。通过将“反向”更改为其他内容(无限或其他提供的选项),它可以防止动画发生。知道我能做些什么来解决这个问题吗?

另外,有人知道产生更鲜艳色彩的更好方法吗?我查看的所有内容都已过时。

4

3 回答 3

6

除了一件事之外,您所做的一切都是正确的:每 3 秒,您会随机生成2种颜色。所以,这就是正在发生的事情:

第一次迭代

color1 生成

color2 生成

视图的背景设置为 color1。然后背景从 color1 变为 color2。

//一切都好

第二次迭代

有一种新颜色1

有一种新颜色2

视图的背景设置为new color1。即时变化会导致频闪灯效果。然后背景从新颜色1变为新颜色2。

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

@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;

另外,请注意,您ObjectAnimator 3 秒创建一个新的:

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 秒更新一次颜色值。

于 2013-09-24T01:17:54.260 回答
2

使用带有 ArgbEvaluator的ObjectAnimator怎么。使用 ObjectAnimator,如果对象具有适当的 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();

有关属性动画的更一般和详细描述:

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

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

于 2013-09-16T00:33:33.370 回答
1

还有另一种如何改变背景颜色的方法;

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

这种方法还具有可用的 trans.reverseTransition(duration) 等方法。

于 2013-09-24T01:32:17.263 回答