Reputation: 19
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
Reputation: 36045
It doesn't update because you're sleeping on the main thread. Whenever you use View#post
or 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
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