Changing background of button every second

709 views Asked by At

I have an activity with 8 buttons in it. I want the backgrounds for all the buttons to randomly change between each other every second that the activity is running. To do this I use the following code:

public class CoinFrenzy extends Activity {

    private  int draw1 = R.drawable.buttonshape1;
    private  int draw2 = R.drawable.buttonshape2;
    private  int draw3 = R.drawable.buttonshape3;
    private  int draw4 = R.drawable.buttonshape4;
    private int draw5 = R.drawable.buttonshape5;
    private int draw6 = R.drawable.buttonshape6;
    private int draw7 = R.drawable.buttonshape7;
    private int draw8 = R.drawable.buttonshape8;
    private ArrayList<Integer> selector = new ArrayList<>();
    private ArrayList<Button> buttonlist = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_coin_frenzy);
         Button btn1 = (Button) findViewById(R.id.angry_btn);
         Button btn2 = (Button) findViewById(R.id.angry_btn2);
          Button btn3 = (Button) findViewById(R.id.angry_btn3);
         Button btn4 = (Button) findViewById(R.id.angry_btn4);
         Button btn5 = (Button) findViewById(R.id.angry_btn5);
          Button btn6 = (Button) findViewById(R.id.angry_btn6);
         Button btn7 = (Button) findViewById(R.id.angry_btn7);
         Button btn8 = (Button) findViewById(R.id.angry_btn8);
        buttonlist.add(btn1);
        buttonlist.add(btn2);
        buttonlist.add(btn3);
        buttonlist.add(btn4);
        buttonlist.add(btn5);
        buttonlist.add(btn6);
        buttonlist.add(btn7);
        buttonlist.add(btn8);
        selector.add(draw1);
        selector.add(draw2);
        selector.add(draw3);
        selector.add(draw4);
        selector.add(draw5);
        selector.add(draw6);
        selector.add(draw7);
        selector.add(draw8);
        h.postDelayed(myRunnable, 1000);


    }

    public static int randInt(int min, int max) {

        // NOTE: Usually this should be a field rather than a method
        // variable so that it is not re-seeded every call.
        Random rand = new Random();

        // nextInt is normally exclusive of the top value,
        // so add 1 to make it inclusive
        int randomNum = rand.nextInt((max - min) + 1) + min;

        return randomNum;
    }

    private Handler h = new Handler(Looper.getMainLooper());

    private Runnable myRunnable = new Runnable() {
        public void run() {
            for (Integer x : selector) {
                int randomInt = randInt(0, 7);
                int back = selector.get(randomInt);
                Button currbtn = buttonlist.get(randomInt);
                currbtn.setBackgroundResource(back);

            }

            //run again in one second
                h.postDelayed(myRunnable, 1000);

        }};

However, after one second passes my app crashes without any logcat errors.

3

There are 3 answers

3
AterLux On

Replace your

private Handler h = new Handler();

to

private Handler h = new Handler(Looper.getMainLooper());

otherwise your code will be run outside the UI thread

2
Garima Mathur On

First do these 2 things:

  1. You have to remove change the background of the button code from thread. This is the main cause of crash. Below you can find two methods on how can one run a code on the main/UI thread on android:
  2. runOnUIThread Activity’s method

    runOnUiThread(new Runnable() {
        public void run() {
            // change background color here
        }
    });
    
  3. Handler

    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
     public void run() {
          // UI code goes here
     }
    });
    

you might want to use one of the two methods whenever you want to update the UI like updating colors on views or other UI related stuff. Otherwise, the application might crash because the UI classes on Android are not thread safe.

This will help you!!

0
Garima Mathur On

You have to pass dynamic index into

int randomInt = randInt(0, 7);

you are always passing same values for min is 0 and max is 7, so it doesn't change any background.

Use selector random ids replace 7 with dynamic loop value x.

private Runnable myRunnable = new Runnable() {
        public void run() {
            for (Integer x : selector) {
                int randomInt = randInt(0, x);
                int back = selector.get(randomInt);
                Button currbtn = buttonlist.get(randomInt);
                currbtn.setBackgroundResource(back);

            }

            //run again in one second
                h.postDelayed(myRunnable, 1000);

        }};

It would be helpful to you.