3

I have a list of hex colors with a duration in milliseconds for each one. I would like to fill the screen with each color for its duration, then move on to the next color.

I tried to iterate over the colors to do the following:

 myView.setBackgroundColor(Color.parseColor( theColor ));
 SystemClock.sleep( theDuration );

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

 etc...

which seemed obvious to me but doesn't do anything to the view when it's running, at least in my AVD. I'm learning that it's because Android only draws at predefined times. (I tried calling "Invalidate()" as well with no luck.)

What is the best way to display all the colors consecutively?

(I realize I shouldn't be calling sleep() either, so any suggestions for that would also be appreciated.)

Thanks.

ScottyB
  • 2,167
  • 1
  • 30
  • 46
  • Any chance you could post more of the code in this class/activity? It'd be helpful to see what method this is in or what else it's interacting with – Alex Feb 04 '14 at 23:02

3 Answers3

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();

Put this in a method and call it.

  • (My previous comment was posted prematurely...) I ended up creating a Runnable inside the my button click event handler. Everything (looping through the colors and durations plus "sleeping" based on the durations) is done in the Runnable. Then I created a handler inside my UI Activity class that just changes the color of the background. The Runnable sends a message to the handler containing the background color using Bundle/Message objects. – ScottyB Feb 05 '14 at 16:05
0

There are many ways to achieve what you want. One could be to use Handler and Runnable. Assuming you know how to get current color and duration, you could do:

  • declare Runnable as class variable

    private Runnable runnable = null;
    
  • inside onCreate(), after you set initial view, initialise Handler

    final Handler handler = new Handler();
    
  • initialise runnable and change the background in run() method

    runnable = new Runnable() {
        @Override
        public void run() {
            //change the color
            myView.setBackgroundColor(currentColor);
    
            //run it again in nextDuration miliseconds
            handler.postDelayed(toggle, nextDuration);
        }
    };
    
    //start runnable in theDuration miliseconds
    handler.postDelayed(toggle, theDuration);
    

You could have arrays of colors and durations and cycle through them with index variable. This is assuming that myView is a valid view.

EDIT:

To those who downvoted, read the documentation for Handler:

When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it...

In other words, you are creating a handler in onCreate() of your activity, so it will be able to update your view.

This blogpost from adroid-developers website uses very similar construct as proposed above.

The Handler runs the update code as a part of your main thread, avoiding the overhead of a second thread and also making for easy access to the View hierarchy used for the user interface.

See here and here answered by CommonsWare and here - answered by Laith Alnagem.

Community
  • 1
  • 1
Melquiades
  • 8,496
  • 1
  • 31
  • 46
  • 1
    I understood that Runnables can't run on the UI thread, so they can't modify View objects. Doesn't it need to send a message to the UI thread to tell it to update the background color? – ScottyB Feb 05 '14 at 05:26
  • @ScottBowers, please check the updated answer. To the downvoter - explain why. – Melquiades Feb 05 '14 at 16:08
  • I didn't downvote it since I'm pretty new to Android/Java programming and am still learning. Thanks for the explanation. But since the Handler is part of the UI thread, won't it "lock" the UI during its duration and (possibly) cause Android to display a warning to the user? – ScottyB Feb 05 '14 at 16:15
  • As the Android blogpost says: "Just remember to keep such tasks small and light to avoid slowing down the user experience.", and you're just changing background color, so you should be fine. Check the links if you still have doubts. – Melquiades Feb 05 '14 at 16:20
0

I ended up creating a Runnable inside the my button click event handler. Everything (looping through the colors and durations plus "sleeping" based on the durations) is done in the Runnable run() method.

public void playOnClick(View v) {
    Runnable runnable = new Runnable() {
        public void run() {
            ...
        }

Then I created a handler inside my UI Activity class that just changes the color of the background.

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));
    }
};

Inside the run() method, he Runnable sends a message to the handler containing the background color using Bundle/Message objects:

b = new Bundle();
b.putString("color", theColor);
msg = new Message();
msg.setData(b);
handler.sendMessage(msg);
ScottyB
  • 2,167
  • 1
  • 30
  • 46