I am using runnable and handler. I want to rotate the view at the same time.
This is my source:
public void rotateImage(final View myView, final int size) {
myHandler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
int time = (2 * 60 * 1000) / 150;
if (size > time) {
myHandler.removeCallbacks(this);
return;
}
myView.setRotation(myView.getRotation() + size);
rotateImage(myView, size);
}
};
myHandler.postDelayed(runnable, 150);
}
It's working, and I can rotate the view every 150 milliseconds, but now I want to pause/stop the thread, for example after two minutes.
How can I do that?
you can calculate the number of iteration you need to get to 2mins, and change you runnable this way
#Override
public void run() {
if (currentIteration > mTotalIterations) {
myHandler.removeCallbacks(this);
currentIteration = 0;
return;
}
++currentIteration;
myView.setRotation(myView.getRotation() + size);
rotateImage(myView, size);
myHandler.postDelayed(this, 150);
}
you have to create only one runnable and only one handler
Related
I'm going to make several images that are to be changing by Handler when they are clicked.
But now there are only two images for a test.
I want to change the images in two processes of clicking on them.
The first process should be stopped when the imaged was clicked again.
In my code, however, the first process doesn't stop.
I can see that both processes are simultaneously acting along.
How can I stop the first thread, and how can I manage one by one when there are many threads are going on?
Here is my code below.
public class MainActivity extends AppCompatActivity {
ImageView img;
ImageView img2;
ImageView img3;
Button btn;
Handler myHandler;
Runnable myRun;
int flag_number;
int img1_phase = 0;
//click method for image 1
public void img1_click (View view) {
flag_number = 1;
click_change_Image(img, img1_phase);
myRun = new Runnable() {
#Override
public void run() {
time_change_image(img, img1_phase);
}
};
new Thread(myRun).start();
}
}
//Click method for 2nd process
public void click_change_Image(final ImageView imageView, int phase) {
if (phase == 4 || phase == 5) {
imageView.setImageResource(R.drawable.second_1);
myHandler.removeCallbacksAndMessages(null); //this code doesn't work
Thread.interrupted();// not work either
phase = 7;
}
image_checker(phase);
return;
}
//Change Image Process by Thread after Clicked
public void time_change_image(final ImageView imageView, int phase) {
if (phase == 0) {
change_Image(imageView, R.drawable.new_one_1, 300);
phase = 1;
image_checker(phase);
change_Image(imageView, R.drawable.new_one_2, 300);
phase = 2;
image_checker(phase);
change_Image(imageView, R.drawable.first_1, 300);
phase = 3;
image_checker(phase);
change_Image(imageView, R.drawable.first_2, 3000);
phase = 4;
image_checker(phase);
change_Image(imageView, R.drawable.first_3, 3000);
phase = 5;
image_checker(phase);
change_Image(imageView, R.drawable.first_4, 3000);
phase = 6;
image_checker(phase);
change_Image(imageView, R.drawable.empty, 3000);
phase = 0;
image_checker(phase);
}else if(phase == 7) {
change_Image(imageView, R.drawable.second_2, 3000);
phase = 8;
image_checker(phase);
change_Image(imageView, R.drawable.second_3, 3000);
phase = 9;
image_checker(phase);
change_Image(imageView, R.drawable.second_4, 3000);
phase = 10;
image_checker(phase);
change_Image(imageView, R.drawable.empty, 3000);
phase = 0;
image_checker(phase);
}
flag_number = 0;
}
//Change Image Resource method
public void change_Image(final ImageView iv, final int image, int wait_time) {
sleep_Thread(wait_time);
myHandler.post(new Runnable() {
#Override
public void run() {
iv.setImageResource(image);
}
});
}
}
Using a flag to manage your thread. For instance:
boolean isRun = true (global variable)
myRun = new Runnable() {
#Override
public void run() {
if(isRun) {
time_change_image(img, img1_phase);
}
}
};
Use Handler to avoid delay in main thread.
Handler mHandler = new Handler();
to start a thread:
mHandler.post(Runnable);
or
mHandler.postDelayed(Runnable, some delayTime)
to stop
mHandler.removeCallback(Runnable);
I have an ImageButton and I want to make it fade in randomly and fade out after some time.
How can I do this?
With a thread? with a service? with something else?
Sorry if it is a very novice question. Thank you
This will fade in/out the imageButton in random interval of 1-5 seconds.
private boolean fadeIn = false;
private final Random rand = new Random();
...
final Handler handler = new Handler(Looper.getMainLooper());
final Runnable runnable = new Runnable() {
#Override
public void run() {
imageButton.animate().alpha(fadeIn ? 1.0f : 0.0f).setDuration(500).withEndAction(new Runnable() {
#Override
public void run() {
fadeIn = !fadeIn;
}
});
handler.postDelayed(this, randInt(1000, 5000));
}
};
handler.post(runnable);
...
public int randInt(int min, int max) {
return rand.nextInt((max - min) + 1) + min;
}
#Override
protected void onDestroy() {
handler.removeCallbacks(runnable);
super.onDestroy();
}
I am trying to create a small animation which changes smoothly the background color. My problem is that it only shows the last value (100, that means it directly goes to a red background). I don't know why my created while-loop doesn't actualize every value (so that it would show a smoothly color animation)
New code (which almost works, but Idk how to stop the animation)
imageButton_info.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
final Handler handler = new Handler();
Runnable ChangeBackgroundRunnable = new Runnable() {
#Override
public void run() {
number++;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
handler.postDelayed(this, 80);
if (number >=100)
number = 1;
}
};
number = 0;
handler.removeCallbacks(ChangeBackgroundRunnable);
handler.postDelayed(ChangeBackgroundRunnable, 0);
}
});
Code:
public void onClick(View v){
try {
while (number<=100) {
number=number+1;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
Thread.sleep(10);
}
}catch(Exception e){
//New exception
Log.e("Camera Error!",e.getMessage());
}
Thank you for your answer in advance...
When you change something in the UI, it doesn't happen immediately. Instead, it posts a message to the Looper on the UI thread. When control returns to the looper (when you're done with whatever function the framework called), it will process all the messages on the Looper, until it eventually processes the redraw request. Then it will draw. So if you're looping in onClick, you will not get any updates to the screen. If you want something to happen in 10ms, post a delayed message to a Handler and update the UI in that thread.
Side note: NEVER EVER sleep on the UI thread. The reason is that no input or draw commands can be processed if you're not returning control to the Looper. So your app becomes unresponsive. If you do it long enough, it can even cause the framework to kill your app for being unresponsive.
A better way to do this would be to use an Android animation. I stole the code for this from here
int colorFrom = getResources().getColor(R.color.red);
int colorTo = getResources().getColor(R.color.blue);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(250); // milliseconds
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animator) {
textView.setBackgroundColor((int) animator.getAnimatedValue());
}
});
colorAnimation.start();
Wrapped the answers posted by #gabe-sechan and #jesse-buss
ValueAnimator support from devices SDK above HONEYCOMB. So below that SDK level we'll use #gabe-sechan suggestion. Check the below code.
private void executeBackgroundChange() {
// Handler and runnable to run the animation in devices sdk below honeycomb.
mHandler = new Handler();
mChangeBackgroundRunnable = new Runnable() {
#Override
public void run() {
number++;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
mContainer.setBackgroundColor(Color.HSVToColor(hsvColor));
mHandler.postDelayed(this, 500);
if (number == 100)
number = 0;
}
};
number = 0;
mHandler.removeCallbacks(mChangeBackgroundRunnable);
mHandler.postDelayed(mChangeBackgroundRunnable, 0);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void executeBackgroundChangeUsingValueAnimator() {
colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), getResources().getColor(R.color.red), getResources().getColor(R.color.blue));
colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(final ValueAnimator animator) {
mContainer.setBackgroundColor((Integer) animator.getAnimatedValue());
}
});
colorAnimation.setRepeatCount(ValueAnimator.INFINITE);
colorAnimation.setDuration(10 * 1000);
colorAnimation.start();
}
Add the below method and to stop the animation on click of something call the below method.
private void stopBackgroundChangeAnimation() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
if (colorAnimation != null && colorAnimation.isRunning())
colorAnimation.end();
} else {
if (mHandler != null && mChangeBackgroundRunnable != null)
mHandler.removeCallbacks(mChangeBackgroundRunnable);
}
}
Check the github project for reference.
Try to use runOnUiThread
public void onCreate(Bundle savedInstanceState) {
res = getResources();
super.onCreate(savedInstanceState);
setContentView(R.layout.xyz);//**Works**/
handler.postDelayed(runnable, 10);
}
private Runnable runnable = new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
public void run()
{
try {
while (number<=100) {
number=number+1;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
}
}catch(Exception e){
//New exception
}
}
});
}
}
i am trying trying to change the background color to red after 1 min of timer and also i want to change background color to yellow after 1min 30 secs of timer in android. This is the code i am trying with, but its not working.
public void run() {
timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
updatedTime = timeSwapBuff + timeInMilliseconds;
int secs = (int) (updatedTime / 1000);
int mins = secs / 60;
secs = secs % 60;
int milliseconds = (int) (updatedTime % 1000);
timerValue.setText("" + mins + ":"
+ String.format("%02d", secs) + ":"
+ String.format("%03d", milliseconds));
if(mins==1)
{
View someView = findViewById(R.id.screen);
//View root = someView.getRootView();
someView.setBackgroundColor(Color.RED);
}
customHandler.postDelayed(this, 0);
}
};
Even simpler
final View someView = findViewById(R.id.screen);
someView.postDelayed(new Runnable() {
public void run() {
someView.setBackgroundColor(Color.RED);
}
},TimeUnit.MINUTES.toMillis(1));
I think you should handle UI views in runOnUiThread.
if(mins==1)
{
runOnUiThread(new Runnable() {
#Override
public void run() {
View someView = findViewById(R.id.screen);
//View root = someView.getRootView();
someView.setBackgroundColor(Color.RED);
}
});
}
Try this:
private static final ScheduledExecutorService worker =
Executors.newSingleThreadScheduledExecutor();
Runnable task = new Runnable() {
public void run() {
View someView = findViewById(R.id.screen);
someView.setBackgroundColor(Color.RED);
}
};
worker.schedule(task, 60, TimeUnit.SECONDS);
Hope it helps.
From : https://stackoverflow.com/a/3072338/5778152
I did something similar a few time ago.
First of all into your layout (could be RelativeLayout or other):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="#+id/screen"
android:layout_width="match_parent"
android:layout_height="match_parent">
//…what you want
</RelativeLayour>
Then in your activity:
//global variables
private long addedTime;
private Handler handler;
private RelativeLayout screen;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
screen = (RelativeLayout) findViewById(R.id.screen);
}
private void start(){
addedTime = 60;
long changeTime = (Calendar.getInstance().getTimeInMillis()/1000) + addedTime;
handler = new Handler() {
#SuppressWarnings("ResourceType")
#Override
public void handleMessage(Message msg) {
if (addedTime == 60) {
screen.setBackgroundColor(Color.parseColor("#ff0000"));//red
addedTime = 120;
}else{
screen.setBackgroundColor(Color.parseColor("#ffff00"));//yellow
addedTime = 60;
}
changeTime = changeTime + addedTime;//add time for the new color change
handler.postDelayed(getRunnable(changeTime), 1000);
super.handleMessage(msg);
}
};
handler.postDelayed(getRunnable(changeTime), 1000);
}
private Runnable getRunnable(final long time) {
return new Runnable() {
#Override
public void run() {
Message message;
Calendar calendar = Calendar.getInstance();
if (calendar.getTimeInMillis() / 1000 == time) {
message = new Message();
handler.sendMessage(message);
} else {
handler.postDelayed(getRunnable(time),1000);
}
}
};
}
The above example will made an infinite loop, so watch out.
Hope to be usefull for you
You can do this in RGB ways. If you want to change color softly during time you can also check this way.
val countDownTimer = object : CountDownTimer(totalTime, 20) {
override fun onFinish() {
}
override fun onTick(millisUntilFinished: Long) {
val pr = (totalTime - millisUntilFinished).toFloat() / totalTime
if(pr <= 1f && pr>=0f){
binding.pbTimerRect.progress = pr
if ((pr * 255).toInt() <= 255) {
if(pr<=0.5) {
binding.lytTimerBackGround.background.setTint(Color.rgb((pr*2* 255).toInt(), 255, 0))
} else {
binding.lytTimerBackGround.background.setTint(Color.rgb(255,(255-((pr-0.5)*2* 255).toInt()), 0))
}
}
}
} else {
if(pr<0) {
onFinish()
}
}
}
}
How to animate multiple objects one by one after some intervals android
i am using this code for animation
for (int y = 0; y < 10; y++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.start();
}
});
}
but it is animating all in one go but i want one by one animation of my imageview please help
No need to use Threads and Handlers. Instead of that use,
objectAnimator.setStartDelay(delay);
Using that you can stop that animation for the respective 'delay'
Try this code..
int delay = 1000;
for (int y = 0; y < 10; y++) {
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.setStartDelay(delay);
oa.start();
delay = delay+1000;
}
You can use for loop to generate AnimatorSet and then play them sequentially using set.playSequentially(yourAnimatorSetListHere);
I haven't used list in below mentioned snippet.
AnimatorSet decSet = new AnimatorSet();
decSet.playTogether(
ObjectAnimator.ofArgb(mTextSlidetoCancel, "visibility", View.GONE, View.VISIBLE),
ObjectAnimator.ofArgb(mBtnMicActive, "visibility", View.GONE, View.VISIBLE),
ObjectAnimator.ofArgb(mChronometer, "visibility", View.GONE, View.VISIBLE));
decSet.setDuration(125);
AnimatorSet decSet2 = new AnimatorSet();
decSet2.playTogether(
ObjectAnimator.ofArgb(mBtnAttach, "visibility", View.VISIBLE, View.GONE),
ObjectAnimator.ofArgb(mBtnEmoji, "visibility", View.VISIBLE, View.GONE),
ObjectAnimator.ofArgb(mEditTExt, "visibility", View.VISIBLE, View.GONE)
);
decSet2.setDuration(125);
AnimatorSet set = new AnimatorSet();
set.playSequentially(decSet2,decSet);
set.start();
Try out this way!
public Integer[] Imgid = {R.drawable.anim2, R.drawable.anim3,
R.drawable.anim4, R.drawable.anim5}; // your image array.
Animation anim;
Handler handler;
ImageView iv;
int count;
Runnable galleryAnimRunnable;
Inside onCreate
iv= (ImageView)findViewById(R.id.imagetype);
handler = new Handler();
galleryAnimRunnable = new Runnable() {
public void run() {
if(count==Imgid.length){
//do any action
}
else{
anim = AnimationUtils.loadAnimation(AnimationScreen.this, R.anim.fade_out); // load your desire animation.
iv.setBackgroundResource(Imgid[count]);
iv.setAnimation(anim);
count++;
handler.postDelayed(galleryAnimRunnable, 300); //set your desire delay time.
}
}
};
Your sleep call isn't helping because when one posted UI job goes to sleep, then next one starts and goes to sleep immediately following that, and so on. Then the first job wakes up and runs, followed closely by the second job awakening and running, etc.
If you want the sleep to help you need to wait before posting each job, which could be as simple as something like the following:
for (int y = 0; y < 10; y++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.start();
}
});
}
EDIT: Although the above explains why you were having problems, I would recommend going with something like the answer posted by Jgdsh Seerm using setStartDelay().
Try this way!
ImageView image1;
public int currentimageindex1=0;
Timer timer;
TimerTask task;
private Animation animation1;
private Animation animation2;
int img[] = {R.drawable.aa, R.drawable.bb,
R.drawable.cc,R.drawable.dd,R.drawable.ee,R.drawable.ff,R.drawable.gg,
R.drawable.hh};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
AnimateandSlideShow();
}
};
int delay = 1000; // delay for 1 sec.
int period = 4000; // repeat every 4 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
mHandler.post(mUpdateResults);
}
}, delay, period);
}
public void onClick(View v) {
finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
/**
* Helper method to start the animation on the splash screen
*/
private void AnimateandSlideShow() {
image1 = (ImageView)findViewById(R.id.imageView1);
image1.setImageResource(img[currentimageindex1%img.length]);
currentimageindex1++;
}