While 循环:更改背景颜色
While loop: Change Background color
我正在尝试创建一个可以平滑改变背景颜色的小动画。我的问题是它只显示最后一个值(100,这意味着它直接进入红色背景)。我不知道为什么我创建的 while 循环没有实现每个值(这样它会显示平滑的彩色动画)
新代码(几乎可以工作,但不知道如何停止动画)
imageButton_info.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
final Handler handler = new Handler();
Runnable ChangeBackgroundRunnable = new Runnable() {
@Override
public void run() {
number++;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
handler.postDelayed(this, 80);
if (number >=100)
number = 1;
}
};
number = 0;
handler.removeCallbacks(ChangeBackgroundRunnable);
handler.postDelayed(ChangeBackgroundRunnable, 0);
}
});
代码:
public void onClick(View v){
try {
while (number<=100) {
number=number+1;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
Thread.sleep(10);
}
}catch(Exception e){
//New exception
Log.e("Camera Error!",e.getMessage());
}
提前感谢您的回答...
当您在 UI 中更改某些内容时,它不会立即发生。相反,它 post 向 UI 线程上的 Looper 发送了一条消息。当控制 returns 到 Looper 时(当你完成框架调用的任何函数时),它将处理 Looper 上的所有消息,直到它最终处理重绘请求。然后它会绘制。因此,如果您在 onClick 中循环,您将不会获得任何屏幕更新。如果您希望在 10 毫秒内发生某些事情,post 向处理程序发送延迟消息并更新该线程中的 UI。
旁注:永远不要在 UI 线程上休眠。原因是如果您不将控制权返回给 Looper,则无法处理任何输入或绘制命令。所以你的应用程序变得没有响应。如果你这样做的时间足够长,它甚至会导致框架因为没有响应而终止你的应用程序。
更好的方法是使用 Android 动画。我从 here
那里偷了代码
int colorFrom = getResources().getColor(R.color.red);
int colorTo = getResources().getColor(R.color.blue);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(250); // milliseconds
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
textView.setBackgroundColor((int) animator.getAnimatedValue());
}
});
colorAnimation.start();
包装了@gabe-sechan 和@jesse-buss
发布的答案
ValueAnimator
来自 HONEYCOMB
以上设备 SDK 的支持。因此,在该 SDK 级别以下,我们将使用 @gabe-sechan 建议。检查下面的代码。
private void executeBackgroundChange() {
// Handler and runnable to run the animation in devices sdk below honeycomb.
mHandler = new Handler();
mChangeBackgroundRunnable = new Runnable() {
@Override
public void run() {
number++;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
mContainer.setBackgroundColor(Color.HSVToColor(hsvColor));
mHandler.postDelayed(this, 500);
if (number == 100)
number = 0;
}
};
number = 0;
mHandler.removeCallbacks(mChangeBackgroundRunnable);
mHandler.postDelayed(mChangeBackgroundRunnable, 0);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void executeBackgroundChangeUsingValueAnimator() {
colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), getResources().getColor(R.color.red), getResources().getColor(R.color.blue));
colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(final ValueAnimator animator) {
mContainer.setBackgroundColor((Integer) animator.getAnimatedValue());
}
});
colorAnimation.setRepeatCount(ValueAnimator.INFINITE);
colorAnimation.setDuration(10 * 1000);
colorAnimation.start();
}
添加以下方法并在单击某项时停止动画调用以下方法。
private void stopBackgroundChangeAnimation() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
if (colorAnimation != null && colorAnimation.isRunning())
colorAnimation.end();
} else {
if (mHandler != null && mChangeBackgroundRunnable != null)
mHandler.removeCallbacks(mChangeBackgroundRunnable);
}
}
检查 github project 以供参考。
尝试使用runOnUiThread
public void onCreate(Bundle savedInstanceState) {
res = getResources();
super.onCreate(savedInstanceState);
setContentView(R.layout.xyz);//**Works**/
handler.postDelayed(runnable, 10);
}
private Runnable runnable = new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
public void run()
{
try {
while (number<=100) {
number=number+1;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
}
}catch(Exception e){
//New exception
}
}
});
}
}
我正在尝试创建一个可以平滑改变背景颜色的小动画。我的问题是它只显示最后一个值(100,这意味着它直接进入红色背景)。我不知道为什么我创建的 while 循环没有实现每个值(这样它会显示平滑的彩色动画)
新代码(几乎可以工作,但不知道如何停止动画)
imageButton_info.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
final Handler handler = new Handler();
Runnable ChangeBackgroundRunnable = new Runnable() {
@Override
public void run() {
number++;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
handler.postDelayed(this, 80);
if (number >=100)
number = 1;
}
};
number = 0;
handler.removeCallbacks(ChangeBackgroundRunnable);
handler.postDelayed(ChangeBackgroundRunnable, 0);
}
});
代码:
public void onClick(View v){
try {
while (number<=100) {
number=number+1;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
Thread.sleep(10);
}
}catch(Exception e){
//New exception
Log.e("Camera Error!",e.getMessage());
}
提前感谢您的回答...
当您在 UI 中更改某些内容时,它不会立即发生。相反,它 post 向 UI 线程上的 Looper 发送了一条消息。当控制 returns 到 Looper 时(当你完成框架调用的任何函数时),它将处理 Looper 上的所有消息,直到它最终处理重绘请求。然后它会绘制。因此,如果您在 onClick 中循环,您将不会获得任何屏幕更新。如果您希望在 10 毫秒内发生某些事情,post 向处理程序发送延迟消息并更新该线程中的 UI。
旁注:永远不要在 UI 线程上休眠。原因是如果您不将控制权返回给 Looper,则无法处理任何输入或绘制命令。所以你的应用程序变得没有响应。如果你这样做的时间足够长,它甚至会导致框架因为没有响应而终止你的应用程序。
更好的方法是使用 Android 动画。我从 here
那里偷了代码int colorFrom = getResources().getColor(R.color.red);
int colorTo = getResources().getColor(R.color.blue);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(250); // milliseconds
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
textView.setBackgroundColor((int) animator.getAnimatedValue());
}
});
colorAnimation.start();
包装了@gabe-sechan 和@jesse-buss
发布的答案ValueAnimator
来自 HONEYCOMB
以上设备 SDK 的支持。因此,在该 SDK 级别以下,我们将使用 @gabe-sechan 建议。检查下面的代码。
private void executeBackgroundChange() { // Handler and runnable to run the animation in devices sdk below honeycomb. mHandler = new Handler(); mChangeBackgroundRunnable = new Runnable() { @Override public void run() { number++; float[] hsvColor = {0, 1, 1}; hsvColor[0] = 360f * number / 100; mContainer.setBackgroundColor(Color.HSVToColor(hsvColor)); mHandler.postDelayed(this, 500); if (number == 100) number = 0; } }; number = 0; mHandler.removeCallbacks(mChangeBackgroundRunnable); mHandler.postDelayed(mChangeBackgroundRunnable, 0); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private void executeBackgroundChangeUsingValueAnimator() { colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), getResources().getColor(R.color.red), getResources().getColor(R.color.blue)); colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(final ValueAnimator animator) { mContainer.setBackgroundColor((Integer) animator.getAnimatedValue()); } }); colorAnimation.setRepeatCount(ValueAnimator.INFINITE); colorAnimation.setDuration(10 * 1000); colorAnimation.start(); }
添加以下方法并在单击某项时停止动画调用以下方法。
private void stopBackgroundChangeAnimation() { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { if (colorAnimation != null && colorAnimation.isRunning()) colorAnimation.end(); } else { if (mHandler != null && mChangeBackgroundRunnable != null) mHandler.removeCallbacks(mChangeBackgroundRunnable); } }
检查 github project 以供参考。
尝试使用runOnUiThread
public void onCreate(Bundle savedInstanceState) {
res = getResources();
super.onCreate(savedInstanceState);
setContentView(R.layout.xyz);//**Works**/
handler.postDelayed(runnable, 10);
}
private Runnable runnable = new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
public void run()
{
try {
while (number<=100) {
number=number+1;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
}
}catch(Exception e){
//New exception
}
}
});
}
}