I'm doing a simple animation app in Android. This is the scenario. I have a button and 4 textviews. When the user clicks the button, the first textview should begin animating (blinking effect) and next the second textview and so on. This is what I've tried so far:
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
btGo.setEnabled(false);
glowCircuit2();
glowCircuit3();
glowCircuit4();
}
private void glowCircuit2() {
new Thread(new Runnable()
{
#Override
public void run()
{
while (!Thread.interrupted())
try
{
Thread.sleep(3000);
runOnUiThread(new Runnable() // start actions in UI thread
{
#Override
public void run()
{
// this action have to be in UI thread
tvCircuit2.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.activecircuit, 0, 0);
tvCircuit2.startAnimation(animBlink);
}
});
}
catch (InterruptedException e)
{
// ooops
}
}
}).start(); // the while thread will start in BG thread
}
private void glowCircuit3() {
new Thread(new Runnable()
{
#Override
public void run()
{
while (!Thread.interrupted())
try
{
Thread.sleep(3000);
runOnUiThread(new Runnable() // start actions in UI thread
{
#Override
public void run()
{
// this action have to be in UI thread
tvCircuit3.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.activecircuit, 0, 0);
tvCircuit3.startAnimation(animBlink);
}
});
}
catch (InterruptedException e)
{
// ooops
}
}
}).start(); // the while thread will start in BG thread
}
private void glowCircuit4() {
new Thread(new Runnable()
{
#Override
public void run()
{
while (!Thread.interrupted())
try
{
Thread.sleep(3000);
runOnUiThread(new Runnable() // start actions in UI thread
{
#Override
public void run()
{
// this action have to be in UI thread
tvCircuit4.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.activecircuit, 0, 0);
tvCircuit4.startAnimation(animBlink);
}
});
}
catch (InterruptedException e)
{
// ooops
}
}
}).start(); // the while thread will start in BG thread
}
I'm getting the blinking effect but I'm getting the simultaneous effect. What I want is to wait for each textview to animate, not animate at the same time. Do you have any clever idea to do this? Help is much appreciated. Thanks.
you are using Threads here, you never know which thread gets priority first and which will get started. I suggest you to using handler, create different message id to send empty message to handler, Android do something like this :
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
btGo.setEnabled(false);
handler.sendEmptyMessage(1);
}
Handler handler = new Handler(){
onHandle(Messsage msg)
{
switch (msg.what)
{
case 1 : glowCircuit2();
handler.sendEmptyMessage(2);
break;
case 2: glowCircuit3();
handler.sendEmptyMessage(3);
break;
}
}
};
private void glowCircuit2(){
tvCircuit2.setCompoundDrawablesWithIntrinsicBounds(0,R.drawable.activecircuit, 0, 0);
tvCircuit2.startAnimation(animBlink);
}
change your code
glowCircuit2();
glowCircuit3();
glowCircuit4();
to this
animation.setAnimationListener(new Animation.AnimationListener()
{
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
glowCircuit2();
}
});
animation1.setAnimationListener(new Animation.AnimationListener()
{
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
glowCircuit3();
}
});
animation2.setAnimationListener(new Animation.AnimationListener()
{
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
glowCircuit4();
}
});
like this code start your third animation on second animation end and start fourth animation on third is end.
Related
I am trying to use swipe refresh layout to update some data.
All works fine but a small bug that I can't seem to solve
When I pull to refresh, the animation gets frozen.
I have implemented it this way:
myRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// Do some stuff
// Sleep as a demonstrator of the issue
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
myRefreshLayout.setRefreshing(false);
}
});
and also tried this:
myRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
myRefreshLayout.post(new Runnable() {
#Override
public void run() {
// Do some stuff
// Sleep as a demonstrator of the issue
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
myRefreshLayout.setRefreshing(false);
}
});
}
});
}
});
but the animation remains frozen until the everything is done, and then it just vanishes (because it hits the setRefreshing(false))
After searching a little, I thought it could be the UI that is waiting for the stuff to finish, so I tried to implement it this way:
myRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new Thread(new Runnable() {
#Override
public void run() {
// Do some stuff
// Sleep as a demonstrator of the issue
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
myRefreshLayout.setRefreshing(false);
}
});
}
});
}
});
}
What happens in this case is that the refresh indicator never vanishes, so I guess it is not calling the runOnUiThread
I tried the same thing with the main looper (handler) instead of the runOnUiThread with the same effect.
Is there any neat way of implementing this?
Am I missing some detail?
I tried the steps described above and I also looked on Stack Overflow for similar issues to no avail.
Thanks!
It's right to do refreshing on background thread,and setRefreshing(false) on main thread. The problem is you forgot to call start() after new thread.
myRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new Thread(new Runnable() {
#Override
public void run() {
// Do some stuff
// Sleep as a demonstrator of the issue
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
myRefreshLayout.setRefreshing(false);
}
});
}
}).start();// start the thread here
}
});
}
After click button I would like to change its color, then wait one second and change its color back.
This is my code:
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
t.join();
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
}
It doesn't work. I've checked it with more complex code and debugger and it looks like all UI changes are made collectively after finish this function.
I've found this thread: apply ui changes immediately and tried to put setBackgroundColor() and setClickable() into runOnUiThread function:
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
}
});
But it also doesn't work. What should I do?
Something like this :
private final Handler handler = new Handler();
public void click(final View view) {
view.setBackgroundColor(Color.parseColor("#0000ff"));
view.setClickable(false);
handler.postDelayed(() -> {
view.setBackgroundColor(Color.parseColor("#e2e2e2"));
view.setClickable(true);
}, 1000);
}
#Override protected void onPause() {
super.onPause();
handler.removeCallbacks(null);
}
The question is not very clear. However, I am trying to summarize the question that I have understood from your question.
You are trying to set a button's background color on clicking on it and change it back after some time. If this is the situation, then I think your idea of how threads work is wanting.
In your code, the button will change the color immediately as the sleep that you are using is running in another thread (other than UI thread). The code is executed correctly, however, you cannot see the effect of the Thread.sleep as its running in a separate thread.
So all you need to do here is to change the background color again inside the thread. Modify your code like the following.
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
This should work.
I have created a demo trying to show what the code will do.
However, using Handler in case of updating UI elements in this specific case is recommended. Please see the comments below.
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
}
}, 1000);
}
Not sure why that wouldn't work, but I've done something similar with
delayHandler = new Handler();
delayHandler.postDelayed(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//change stuff on ui
}
});
}
}, 1000);
if that doesn't work the only other functional difference in my code is that instead of btn being a final Button it's a private global variable in my activity.
Hope the following code will help :
btn.setBackgroundColor(Color.RED); // color you want for a second
new CountDownTimer(1000, 1000) {
#Override
public void onTick(long arg0) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
btn.setBackgroundColor(Color.BLUE); //to change back color to prior state
}
}.start();
Try this,i think it's work for you..
final Button bPdf = findViewById(R.id.pdf);
bPdf.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
bPdf.setBackgroundColor(Color.parseColor("#0000ff"));
new CountDownTimer(1000, 50) {
#Override
public void onTick(long arg0) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
bPdf.setBackgroundColor(Color.parseColor("#e2e2e2"));
}
}.start();
}
});
I've got this code:
#Override
public void onClick(View v) {
progressDoalog = new ProgressDialog(Hack.this);
progressDoalog.setMax(100);
progressDoalog.setMessage("Its loading....");
progressDoalog.setTitle("ProgressDialog bar example");
progressDoalog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDoalog.show();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (progressDoalog.getProgress() <= progressDoalog
.getMax()) {
Thread.sleep(200);
handle.sendMessage(handle.obtainMessage());
if (progressDoalog.getProgress() == progressDoalog
.getMax()) {
progressDoalog.dismiss();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
Handler handle = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
progressDoalog.incrementProgressBy(1);
}
};
});
}
}
Where can I add a code to open new activity when the ProgressDialog will be at 100%? Which and where exactly? Thanks for your help!
You can't start an Activity from a Dialog, but what you can do is start the Activity from the old one using a OnDismissListener.
Take a look at the documemtation :
https://developer.android.com/reference/android/content/DialogInterface.OnDismissListener.html
I haven't noticed but you can check the progress in your Handler, check if it's 100%, dismiss the dialog and start the new Activity, remember that you gotta do this on the UI thread
I want to call adapter.notifyDataSetChanged() from another thread. I read that I should use an AsyncTask and do the adapter.notifyDataSetChanged() in post execute.
I must execute the AsyncTask every 5 seconds only on the current activity (might be parent or child activity) because only one activity can do the asynctask at the same time.
Should I create a TimerTask which executes the AsyncTask every 5 seconds, stop it when I start another activity and start it back in onResume ?
Here is my code for the thread which updates the ListView of the current Activity.
private void runEventHandler() {
new Thread() {
public void run() {
while (true) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
users.add(new User(10, "a", false));
adapter.notifyDataSetChanged();
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
Now I must be able to update the child activities' ListViews when a new User is added.
one possible way is that you create a flag in both activity to control your threads to be run ( the following codes are not runable just example to understand what you can do):
Activity A
{
public static boolean stopThread = false;
#Override
public void onResume()
{
super.onResume();
// put your code here...
stopThread =false;
runEventHandler();
}
private void runEventHandler() {
new Thread() {
public void run() {
while (A.stopThread != false) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
users.add(new User(10, "a", false));
adapter.notifyDataSetChanged();
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
#Override
protected void onStop(){
super.onStop();
stopThread =true;
}
}
Activity B
{
public static boolean stopThread = false;
#Override
public void onResume()
{
super.onResume();
// put your code here...
stopThread =false;
runEventHandler();
}
private void runEventHandler() {
new Thread() {
public void run() {
while (B.stopThread != false) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
users.add(new User(10, "a", false));
adapter.notifyDataSetChanged();
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
#Override
protected void onStop(){
super.onStop();
stopThread =true;
}
}
also you can use onPause() instead of onStop(). depends on your program concept.
You should a timertask like in link below : https://examples.javacodegeeks.com/android/core/activity/android-timertask-example/
the code to post any change on UIThread if you are in a different thread like doInBackground of AsyncTask:
runOnUiThread(new Runnable() {
#Override
public void run() {
// Here you can set your Ui Components
}
});
I'm programming a small android app in Java/eclipse.
In one part of my app i need a thread, as i build in the following way:
protected void onResume() {
super.onResume();
// we're going to simulate real time with thread that append data to the graph
new Thread(new Runnable() {
#Override
public void run() {
// we add 100 new entries
for (int i = 0; i < 100; i++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
addEntry();
}
});
// sleep to slow down the add of entries
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// manage error ...
}
}
}
}).start();
}
Evertything works fine so far. But now i want to start that thread not automatically. I want to handle ".start()" with a button.
How can i realize it?
I'm very new to Java and Android.
Thanks in Advance!
You can use Handler with Runnable instead of your Thread idea, Check out the following code, it server your purpose,
private Handler broadcastHandler;
private Runnable broadcastRunnable;
protected void onResume() {
super.onResume();
broadcastRunnable = new Runnable() {
#Override
public void run() {
// Your UI related operations
runOnUiThread(new Runnable() {
#Override
public void run() {
addEntry();
}
});
// Add some delay
broadcastHandler.postDelayed(broadcastRunnable, 1000);
}
}
public void onButtonClick(View view) {
broadcastHandler.postDelayed(broadcastRunnable, 1000);
}