我正在尝试生成随机颜色并将其设置为背景,速度为3秒。我创建了一个thread
来处理这个变化,现在我想在颜色变化之间添加一个过渡,使其融合得很好。
作为参考,请查看this app。
编辑:
我已尝试在循环中使用ObjectAnimator
和ArgbEvaluator
,并且过渡时间为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”导致了这个问题。我还没有修复。通过将“反向”更改为其他内容(无限或其他提供的选项),可以防止动画发生。知道我能做些什么来解决这个问题吗?另外,有没有人知道更好的方式来产生更鲜艳的色彩?我所看到的一切都已经过时了。
答案 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)这样的方法。