Handler post delay not work in for loop - android

Spannable WordtoSpan;
TextView tvView;
public void btnStart(View v)
{
tvView = (TextView)findViewById(R.id.tvTest);
changeColorOfText("I know just how to whisper, And I know just how to cry,I know just where to find the answers.");
}
int sIndexOfWord;
int fIndexOfWord;
private void changeColorOfText(String sentences)
{
String[] arrWords = sentences.split(" ");
WordtoSpan = new SpannableString(sentences);
int k = 1;
for(String word : arrWords) {
sIndexOfWord = sentences.indexOf(word);
fIndexOfWord = sIndexOfWord + word.length();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
WordtoSpan.setSpan(new BackgroundColorSpan(Color.YELLOW), sIndexOfWord, fIndexOfWord, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tvView.setText(WordtoSpan);
}
}, 2000*k++);
}
}
This code not work, just color the last text of sentence. How can i color word one by one with handler.postDelayed method.
Thanks.

may be you can try this: call setTextColor() method recursively at interval of 2 seconds
int k = 0;
private void setTxtColor(){
if(k < arrWords.length){
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
sIndexOfWord = sentences.indexOf(arrWords[k]);
fIndexOfWord = sIndexOfWord + word.length();
WordtoSpan.setSpan(new BackgroundColorSpan(Color.YELLOW), sIndexOfWord, fIndexOfWord, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tvView.setText(WordtoSpan);
k++;
setTxtColor();
}
}, 2000);
}
}

The below displays words with green color as the foregr0und for words every 1 second.
Textview will have hello! displayed first with green color and after a delay for 1 second next word will be appended to the textview with green color. This repeats till it reaches the length of string s. If you don't want to append you just set text of the new word
_tv.setText(text); and remove the append part.
Also i have used a timer and set the text on the ui thread. You can also use a handler.
String s;
int _count=0;//counter
Timer _t;
TextView _tv;
String[] each;//holds each word in an array
Button b;
b= (Button) findViewById(R.id.button1);
_tv = (TextView) findViewById( R.id.tv );
b.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//s=et.getText().toString();
s="hello!. how are you";
_tv.setText("");
for(int i=0;i<s.length();i++)
{
each = s.split("\\s+");
}
_t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
if(_count<=each.length-1)
{
SpannableString text = new SpannableString(each[_count]);
text.setSpan(new ForegroundColorSpan(Color.GREEN), 0,text.length(), 0);
_tv.append(text);
_tv.append(" ");
System.out.println("................"+each[_count]);
_count=_count+1;
}
else
{
_t.cancel();
}
}
});
}
}, 1000, 1000 ); //change to 2000 for 2 second delay.
}
});

Related

Highlight text of String word by word inside card view on button click listener

I have to highlight specific words when I click on a button within a CardView. The text I need to highlight words in is also part of the CardView.
The problem is that when I click on the button the text in other CardViews is also getting highlighted.
What causes this and how do I fix this issue?
This is my code:
#Override
public void onBindViewHolder(final DuaViewHolder duaViewHolder,final int i) {
ci = allDuasLists.get(i);
duaViewHolder.arebicText.setText(ci.getDuas());
duaViewHolder.arebicEuivalantText.setText(ci.getArebicText());
duaViewHolder.nativeText.setText(ci.getNativeText());
mp = new MediaPlayer();
duaViewHolder.playAudio.setBackgroundResource(R.drawable.play_48);
class MyTimer extends CountDownTimer {
public MyTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
WordtoSpan = new SpannableString(CurrentDua);
}
#Override
public void onFinish() {
k=0;
this.cancel();
Toast.makeText(context, "Timer finished", Toast.LENGTH_LONG).show();
}
#Override
public void onTick(long millisUntilFinished) {
WordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), arrString[k], arrString[k + 1], Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
k++;
duaViewHolder.arebicText.setText(WordtoSpan);
}
}
duaViewHolder.playAudio.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ci = allDuasLists.get(i);
CurrentDua = ci.getDuas();
Log.e("Current Dua", CurrentDua);
arrString = new int[CurrentDua.length() + 1];
MakeSubString();
duaViewHolder.playAudio.setBackgroundResource(R.drawable.stop_48);
MyTimer timer = new MyTimer(mp.getDuration() * 1000, 1300);
timer.start();
k = 0;
}
});
}
Here is how it looks like:
Try this way, instead of getting value of ci inside onclicklistener from list
ci = allDuasLists.get(i);
set ci to duaViewHolder.playAudio tag like
duaViewHolder.playAudio.setTag(ci);
and inside onClickListener get it like
ci = /*(Cast to your ci class)*/ v.getTag();

How to change a TextView text and color after a timer starts and after it ends

i am new to app development and i am currently trying to make a counter app.
i have set up the buttons so that the text changes with the button pressed.
although, i am trying to make the text display the adding or subtracting value and then show the total number afterwards.
For example, my counter starts at 20;
if i press the add button i want the textview text to change to +1, +2, +3 and so on for however many times the button is pressed within a time of 2 seconds. After 2 second i want the textview to show the total again. So if i pressed it 3 times, after 2 seconds on the 3rd press i want it to display "23" and not "+3" anymore.
Then, if i pressed the minus button just once the textview will display "-1" and then after 2 seconds change to "22", etc. I also want the text color to change to green when the add button is pressed, red when the minus is pressed and white when displaying the total or at default.
Here is my code so far, i am probably off by a mile but i would really like some help to be shown in the right direction.
public class MainActivity extends Activity {
private Thread timer;
TextView lifepointsP1;
ImageButton p1AddL, p1SubL;
int counter1;
int count;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
counter1 = 20;
count = 0;
lifepointsP1 = (TextView) findViewById(R.id.tvP1LP);
p1AddL = (ImageButton) findViewById(R.id.bP1add);
p1SubL = (ImageButton) findViewById(R.id.bP1take);
//the timer
timer = new Thread() {
#Override
public void run(){
try {
synchronized(this){
wait(2000);
}
} catch(InterruptedException e){
e.printStackTrace();
}
count = 0;
lifepointsP1.setTextColor(Color.argb(0, 0, 0, 0));
}
};
p1AddL.setOnClickListener(new View.OnClickListener() {
//the buttons
public void onClick(View v) {
counter1++;
count++;
if (count == 0) {
if (counter1 >= 9|counter1 <= -1) {
lifepointsP1.setText("" + counter1);
} else {
lifepointsP1.setText("0" + counter1);
}
} else if (count > 0) {
lifepointsP1.setText("+" + count);
lifepointsP1.setTextColor(Color.argb(0, 0, 188, 0));
}
}
});
p1SubL.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
counter1--;
count--;
if (count == 0) {
if (counter1 >= 9|counter1 <= -1) {
lifepointsP1.setText("" + counter1);
} else {
lifepointsP1.setText("0" + counter1);
}
} else if (count < 0) {
lifepointsP1.setText("-" + count);
lifepointsP1.setTextColor(Color.argb(0, 214, 0, 0));
}
}
});
}
//the counter reset if pressed
#Override
public boolean onTouchEvent(MotionEvent evt) {
if(evt.getAction() == MotionEvent.ACTION_DOWN) {
synchronized(timer){
timer.start();
}
}
return true;
}
}
Ive also set it up so that if the button is pressed while the timer is counting it will reset the count to start again.
Thanks in advanced for any help, its really appreciated!
What you need is a CountdownTimer
You can implement your logic in the onFinish() method then.
You should go with Handler class
A Handler allows you to send and process Message and Runnable objects
associated with a thread's MessageQueue. Each Handler instance is
associated with a single thread and that thread's message queue. When
you create a new Handler, it is bound to the thread / message queue of
the thread that is creating it -- from that point on, it will deliver
messages and runnables to that message queue and execute them as they
come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed as some point in the future; and (2) to
enqueue an action to be performed on a different thread than your own.
public int i = 0;
Then:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(i != 20) {
text.append(" " + i);
i++;
handler.postDelayed(this, 1000);
} else {
handler.removeCallbacks(this);
text.append(" Stopped");
}
}
}, 1000);
}

resolve 'called from wrong thread' exception

The purpose of my app is: User enters a number and clicks a button. The button uses the input to calculate the Fibonacci sequence with a timer - with each number in the sequence displaying each second to a textView. But when I try to run the timer I get the CalledFromWrongThreadException. I've posted my code below. As you can tell by my log statements I believe I know which line is causing the problem. I think it's because I'm calling a method which is outside my onclicklistener but when I move that other method around I just cause more problems.
I've read a couple other posts and I'm not really sure what the proper way is to print to a text area using my method. Does anyone know how I can make this work?
public class MainActivity extends Activity {
// primary widgets
private EditText editText;
private TextView textView;
private Button button1;
static int seconds = 0;
static Timer timer;
static ArrayList<Integer> fibList = new ArrayList<Integer>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText1);
textView = (TextView) findViewById(R.id.textView2);
button1 = (Button) findViewById(R.id.button1);
final int delay = 1000;
final int period = 1000;
timer = new Timer();
//Attempt to clear TextView
textView.setText("");
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Clear Textview
String array = " ";
fibList.clear();
textView.setText(array);
//Log.i("ARRAY", "ATTEMPT to CLEAR"+fibList);
String input = editText.getText().toString();
int number = Integer.parseInt(input);
int tmp = 0;
// confirm input
if (number < 20) {
Toast.makeText(getApplicationContext(),
"You entered: " + number, Toast.LENGTH_LONG).show();
for (int i = 0; i <= number; i++) {
fibList.add(fib(i));
// sum even numbers
if (fib(i) % 2 == 0) {
tmp += fib(i);
}
}
} else {
Toast.makeText(getApplicationContext(),
"Number is too Large: " + number, Toast.LENGTH_LONG)
.show();
}
//I believe error occurs in this method
Log.i("TEST", "START TIMER");
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Log.i("TEST", "RUN TIMER");
int nextIndex = setInterval();
Log.i("TEST", "SET INTERVAL");
if (nextIndex < fibList.size()) {
Log.i("TEST", "TRY TO PRINT");
//It looks like error occurs here when I try to print to textView
textView.setText(fibList.get(nextIndex)+ " ");
Log.i("TEST", "NEXT INDEX"+fibList.get(nextIndex));
Log.i("TEST", "DID PRINT");
}
}
}, delay, period);
Log.i("TEST", "END TIMER");
}
});
}
// run fibonacci sequence
public static int fib(int n) {
if (n < 2) {
return n;
} else {
return fib(n - 1) + fib(n - 2);
}
}
//counts up for every element through the array
public static final int setInterval() {
if (seconds >= fibList.size())
timer.cancel();
return seconds++;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
You can use
runOnUiThread(new Runnable(){
public void run(){
textView.setText("aaa");
}
});
Have your timer post a message to a Handler. The handler will, by default, run on the main thread. IT can then change the UI as needed, so just put the body of your timer into that handler.
I just had this problem and came on to StackOverflow to check out a solution. Didn't find anything proper but a little more experimenting with lot many Logs and debugging got me my solution.
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText("Your String");
}
});
In my code, the problem was due to me accessing Two TextViews in seperate threads one after another using TextView.post(new Runnable...). I guess this was due to it not being able to access UI Thread (as it was busy with previous thread changes). Setting both TextViews together in UI Thread solved the problem. So posting here for anyone else who might be perplexed by similar problem. Hope it helps.

image button changing in android

In my application i'm changing image of button for 1sec.how to compare image of button.i tried a lot.please help me.when i chang image 1st tyme after 1sec its not changing agian.its remain the same.below is the code-
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
if(time==-1){
onStop();
}
else
runOnUiThread(new Runnable() {
public void run() {
Random rand=new Random();
System.out.println("timer...."+time);
time=time-1;
int num = rand.nextInt(buttonIds.length);
int buttonId = buttonIds[num];
Button bb=(Button) findViewById(buttonId);
if((bb.getBackground()).equals(button.getBackground()))
{
bb.setBackgroundResource(R.drawable.happy);
wrong++;
System.out.println("llllllllllll"+wrong);
}
else
{
bb.setBackgroundResource(R.drawable.whoa);
count++;
System.out.println("mmmmmm"+count);
}
}
});
}
},0, 1000);
}
Edit
you are getting the button freshly like this
Button bb=(Button) findViewById(buttonId);
so it will always remains whoa....because the condition is always false.....
I would suggest you to set Content Description while setting the background resource and then compare the content Description....You can't compare by bb.getBackground()).equals(button.getBackground())
do something like this
but1=(Button) findViewById(R.id.b1);
but1.setBackgroundResource(R.drawable.happy);
but1.setContentDescription("happy");
and
if(bb.getContentDescription().equals(button.getContentDescription())

How to reset variable in runnable in Android

I have a handler and a runnable, Handler has a loop that runs from 0 to 5. when i start the runnable in handler it runs and increment value to 0 to 5. But if i double click or click more than 1 time than it takes the value of temp above 5. How can i reset (0) the value of temp on every click of handler.
final Handler deneme = new Handler();
final Runnable post_score = new Runnable(){
public void run(){
Log.i("TAG", Integer.toString(temp));
temp++;
}
};
Button tv = (Button )findViewById(R.id.button1);
tv.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
temp = 0;
for(int i=0; i < 5;i++){
deneme.postDelayed(post_score, i *250);
}
}
});
the best way is to use removecallback

Categories

Resources