【问题标题】:Dynamically change background color with animated transition通过动画过渡动态更改背景颜色
【发布时间】:2013-09-15 23:40:55
【问题描述】:

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

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

【问题讨论】:

  • 运行这段代码会发生什么?
  • 那个线程加上反转动画不会太顺利。看看这个,看看它是否是你想要的gist.github.com/luksprog/6673439

标签: java android animation random colors


【解决方案1】:

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

第一次迭代

color1 生成

color2 生成

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

//一切顺利

第二次迭代

有一种新颜色1

有一种新颜色2

视图的背景设置为新颜色1。立即改变原因 频闪灯效果。然后背景从新的变化 color1 到新的 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;

另外,请注意您正在创建一个新的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 秒更新一次颜色值。

【讨论】:

  • 感谢您提供高质量的答案,它有效!我会在 33 分钟内奖励赏金。
  • @Collin 不客气。这是我见过的最快的赏金交付。谢谢。
  • 我让它工作了,但我需要将它移动到我的主应用程序中,所以我复制了 xml 和 java 类,现在 ObjectAnimator 不能正常工作。它没有我以前工作的淡入淡出效果。我确定我使用的是 API 11,但我不知道为什么这在另一个项目中不起作用。知道是什么原因造成的吗?
  • @Collin 很难猜测在转移过程中发生了什么问题。突然想到:尝试将持续时间设置为略小于睡眠值,例如:anim.setDuration(2900)。此外,属于ObjectAnimator 的一些方法需要API 14。但是,上面的代码没有使用它们中的任何一个。所以,这不可能是问题。您可以发布更新的代码吗?更好的是,使用更新的代码和您正在使用的布局发布一个新问题。在这里给我留下评论和链接,我会看看。
【解决方案2】:

如何使用ObjectAnimatorArgbEvaluator。使用 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库。

【讨论】:

  • 啊,我明白发生了什么。我尝试使用随机颜色动态地执行此操作,但过渡会导致类似频闪的效果,并且基本上会让任​​何用户癫痫发作。你能看看我编辑过的帖子上的新代码吗?
  • 我缩小了范围,发现“.setRepeatMode”导致了问题。我仍然没有修复 - 通过将“反向”更改为其他内容,它可以防止动画发生。有什么想法吗?
【解决方案3】:

如何改变背景颜色的另一种选择;

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-12
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    相关资源
    最近更新 更多