如何在Android/Java中循环显示背景颜色?

3
我有一组十六进制颜色代码,每一个都对应一段时间(单位为毫秒),我希望屏幕能够按照时长显示每种颜色,并在时长结束后切换到下一种颜色。
我曾尝试使用循环迭代来实现以下功能:
 myView.setBackgroundColor(Color.parseColor( theColor ));
 SystemClock.sleep( theDuration );

 myView.setBackgroundColor(Color.parseColor( nextColor ));
 SystemClock.sleep( nextDuration );

 etc...

这对我来说似乎很明显,但在我的AVD上运行时并没有对视图产生任何影响。我了解到这是因为Android只在预定义的时间绘制。 (我也尝试过调用"Invalidate()",但没有成功。)

显示所有颜色连续的最佳方法是什么?

(我意识到我也不应该调用sleep(),所以对此的任何建议也将不胜感激。)

谢谢。


你能否在这个类/活动中发布更多的代码?看到这个方法所在的位置或它正在与什么其他内容交互会很有帮助。 - Alex
3个回答

2
new Thread() {
    @Override
    public void run() {
        YourActivity.this.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            myView.setBackgroundColor(Color.parseColor( theColor ));
        }
        Thread.sleep( theDuration);

        YourActivity.this.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            myView.setBackgroundColor(Color.parseColor( nextColor ));
        }
        Thread.sleep( nextDuration );
    }
}.start();

把这段代码放进一个方法里并调用它。

我最终在按钮点击事件处理程序中创建了一个可运行对象。所有的操作(包括循环遍历颜色和持续时间,以及根据持续时间进行“休眠”)都在可运行对象中完成。然后,我在我的UI活动类中创建了一个处理程序,用于改变背景颜色。可运行对象通过Bundle/Message对象向处理程序发送包含背景颜色的消息。 - ScottyB

0

有很多方法可以实现你想要的效果。其中一种方法是使用Handler和Runnable。假设你知道如何获取当前颜色和持续时间,你可以这样做:

  • 将Runnable声明为类变量

    private Runnable runnable = null;
    
  • 在onCreate()内,设置初始视图后,初始化Handler

    final Handler handler = new Handler();
    
  • 初始化runnable,并在run()方法中更改背景

    runnable = new Runnable() {
        @Override
        public void run() {
            // 更改颜色
            myView.setBackgroundColor(currentColor);
    
            // 在 nextDuration 毫秒后再次运行
            handler.postDelayed(toggle, nextDuration);
        }
    };
    
    // 在 theDuration 毫秒后启动runnable
    handler.postDelayed(toggle, theDuration);
    

你可以使用颜色和持续时间的数组,并通过索引变量循环遍历它们。这是假设myView是一个有效的视图。

编辑:

对于那些给我点踩的人,请阅读Handler的文档:

当你创建一个新的Handler时,它会绑定到创建它的线程/消息队列...

换句话说,你在activity的onCreate()方法中创建了一个handler,因此它能够更新你的视图。

这篇来自adroid-developers网站的博文使用了与上述提出的类似的结构。

Handler作为主线程的一部分来运行更新代码,避免了第二个线程的开销,并且方便访问用户界面所使用的视图层次结构。

请参见这里这里,由CommonsWare回答以及这里,由Laith Alnagem回答


1
我明白Runnables无法在UI线程上运行,因此它们无法修改View对象。难道不需要向UI线程发送消息以告诉它更新背景颜色吗? - ScottyB
@ScottBowers,请检查更新后的答案。给那个踩负评的人解释一下原因。 - Melquiades
我没有给它点踩,因为我是 Android/Java 编程的新手,还在学习中。感谢您的解释。但是由于 Handler 是 UI 线程的一部分,它会在执行期间“锁定”UI,并(可能)导致 Android 向用户显示警告,这样是吗? - ScottyB
正如Android博客文章所说:“只需记住将这些任务保持小而轻,以避免减慢用户体验。”而且你只是在改变背景颜色,所以应该没问题。如果你仍然有疑问,请查看链接。 - Melquiades

0
我最终在按钮点击事件处理程序内创建了一个Runnable。所有操作(循环遍历颜色和持续时间以及根据持续时间“休眠”)都在Runnable的run()方法中完成。
public void playOnClick(View v) {
    Runnable runnable = new Runnable() {
        public void run() {
            ...
        }

然后我在我的UI活动类中创建了一个处理程序,只是改变了背景的颜色。
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        Bundle b = msg.getData();
        String theColor = b.getString("color");

        myView = (View) findViewById(R.id.bigView);
        myView.setBackgroundColor(Color.parseColor(theColor));
    }
};

在run()方法内,Runnable使用Bundle/Message对象向处理程序发送包含背景颜色的消息:
b = new Bundle();
b.putString("color", theColor);
msg = new Message();
msg.setData(b);
handler.sendMessage(msg);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接