Wellyanto the second
Wellyanto the second

Reputation: 19

How to add some delay after each iteration of array, each iterations changes view's property. Android

Lets say i have an array of char (mCharArray), and one textView (tvChar) that is the size of the whole screen. i want that, when the user clicks the screen (the tvChar), the textView shows each char inside the charArray, however it should have like 1 second delay in each iteration. How to accomplish this?

this is the current solution that i had. This code snippet is from the onViewCreated part of a fragment.the problem is, the text doesn't update, it only works for the last element of the char array.

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    tvChar = (TextView) view.findViewById(R.id.tv_char);
    tvChar.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // not sure how to pause after each iteration...
            v.postDelayed(new Runnable() {
                @Override
                public void run() {
                    for (char element : mCharArray) {
                        synchronized (tvChar) {
                            tvChar.setText(String.valueOf(element));

                            tvChar.notify();

                            try {
                                tvChar.wait(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }, 1000);
        }
    });
}

UPDATE: Thanks for all the answers, although none really works when i tried them, you guys help me give some intuition.

I end up adding thread handler on onCreate

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mCharArray = getArguments().getCharArray(SENTENCE_KEY);
    }

    handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            this.obtainMessage();
            tvChar.setText(Character.toString((char)msg.arg1));
        }
    };
}

create a new thread in the setOnclickListener

tvChar.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            thread = new Thread(new ChangeCharThread());
            thread.start();
        }
    });

creating an inner class that implements runnable.

class ChangeCharThread implements Runnable{
    @Override
    public void run() {
        Message msg = Message.obtain();

        for (char ch : mCharArray){
            msg.arg1 = ch;

            handler.sendMessage(msg);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Upvotes: 1

Views: 474

Answers (2)

DeeV
DeeV

Reputation: 36045

It doesn't update because you're sleeping on the main thread. Whenever you use View#postor View#postDelayed you are actually giving the code to a View backed Handler that runs the runnable on the main UI thread. Because you're sleeping on the main thread, the UI is never being updated. You're just constantly updating the textview with new data before the textview even draws again.

What you need to do is instead of looping through all of your character arrays, just do something like this:

boolean running
int count;
tvChar.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (running) {
               running = false;
            } else {
               v.postDelayed(new Runnable() {
                 @Override
                 public void run() {
                    char element = mCharArray[count % mCharArray.length];
                    tvChar.setText(String.valueOf(element));
                    count++;
                    if (running) {
                      v.postDelayed(1000);
                    }
             }, 1000);
        }
    });

Upvotes: 0

ZakiMak
ZakiMak

Reputation: 2102

You could try an approach similar to this inside your click method. Where every UI update is delayed further by a second to synchronize the behavior. What is needed is a schedule for each update:

    for (int i= 0; i< mCharArray.length; i++) {
            EventDetail.handler.postDelayed(new Runnable()
            {
                public void run()
                {
                    tvChar.setText(String.valueOf(mCharArray[i]));
                }
            }, 1000 *(i+1)); 
    }

Upvotes: 1

Related Questions