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();
}
Related
I'm trying to animate the seekbar progress. It works fine when the progress update is not from user(which is what I want) but when the user drags the seekbar, I want the animation to stop. Right now what happens is when user drags the seekbar, the seekbar progress animates and there is delay because of the animation. I hope you guys get what I'm trying to say. I only want the animation when the input is not from user else animate.
Code:
circularSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
circularSeekBar.setEnabled(true);
if(fromUser) {
int seekprogress = (int) circularSeekBar.getProgress();
Intent io = new Intent(ConstantsForBroadCast.ACTION_PLAY_SEEKBAR);
io.putExtra("Progress", seekprogress);
getActivity().sendBroadcast(io);
}
}
public void Handler(final MediaPlayer mp){
currentSongLength= mp.getDuration();
final Handler mHandler = new Handler();
if((Activity)getActivity()!=null) {
((Activity) getActivity()).runOnUiThread(new Runnable() {
#Override
public void run() {
circularSeekBar.setMax((int) currentSongLength / 1000);
int mCurrentPosition = mp.getCurrentPosition() / 1000;
ObjectAnimator animation1 = ObjectAnimator.ofInt(circularSeekBar,"progress", mCurrentPosition);
animation1.setDuration(1000); // 0.5 second
animation1.setInterpolator(new DecelerateInterpolator());
animation1.start();
circularSeekBar.clearAnimation();
mHandler.postDelayed(this, 1000);
}
});
}
I have two Chronometer in an activity.
First Chronometer is for elapsed time, and Second Chronometer is for interval time.
For Ex.:-
We chose 5 Min elapsed time and 30 Seconds interval time, now we start both timers at the same time by pressing btn_start. Both timers start with 0, now when interval timer reaches 00:30 time it restarts again with 0.
Now the issue:-
As I have cross checked both timers start with a difference of milliseconds. Which later becomes a difference of 1 second,2 seconds,3 seconds or more seconds.
Below is Custom Chronometer.Java
public class PausableChronometer extends Chronometer implements PlaybackStateView {
// Keeps track of how far long the Chronometer has been tracking when it's paused. We'd like
// to start from this time the next time it's resumed.
private long timeWhenStopped = 0;
public PausableChronometer(Context context) {
super(context);
}
public PausableChronometer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PausableChronometer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void start() {
setBase(SystemClock.elapsedRealtime() + timeWhenStopped);
Log.e("start()", String.valueOf(SystemClock.elapsedRealtime() + timeWhenStopped));
super.start();
}
#Override
public void stop() {
super.stop();
timeWhenStopped = getBase() - SystemClock.elapsedRealtime();
}
/**
* Reset the timer and start counting from zero.
*/
#Override
public void restart() {
reset();
start();
}
public void reset() {
stop();
setBase(SystemClock.elapsedRealtime());
timeWhenStopped = 0;
}
#Override
public void resume() {
setBase(SystemClock.elapsedRealtime() - timeWhenStopped);
start();
}
#Override
public void pause() {
stop();
timeWhenStopped = SystemClock.elapsedRealtime() - getBase();
}
}
On Button Clicked I execute following:
private void startTimer() {
intervalTimer.start();
elapsedTimer.start();
}
Please let me know, How can I avoid the difference of milliseconds between both Chronometers start time?
As Anton Malyshev said that it's not possible to avoid the difference of start time of two different chronometers.
I used Handler and Runnable to resolve the issue and for me, it works perfectly.
private TextView elapsedTimer, intervalTimer;
Handler mHandlerElapsed = new Handler(), mHandlerInterval = new Handler();
Runnable mRunnableElapsed, mRunnableInterval;
private int nCounterInterval = 0, nCounterElapsed = 0;
Method for timer:-
private void updateTime() {
mHandlerElapsed = new Handler();
mRunnableElapsed = new Runnable() {
#Override
public void run() {
if (!isPause) {
mHandlerElapsed.postDelayed(mRunnableElapsed, 1000);
nCounterElapsed++;
elapsedTimer.setText(AppUtil.formattedTime(nCounterElapsed));
} else {
mHandlerElapsed.removeCallbacks(mRunnableElapsed);
}
}
};
mHandlerElapsed.post(mRunnableElapsed);
mHandlerInterval = new Handler();
mRunnableInterval = new Runnable() {
#Override
public void run() {
if (!isPause) {
mHandlerInterval.postDelayed(mRunnableInterval, 1000);
nCounterInterval++;
intervalTimer.setText(AppUtil.formattedTime(nCounterInterval));
} else {
mHandlerInterval.removeCallbacks(mRunnableInterval);
}
}
};
mHandlerInterval.post(mRunnableInterval);
}
for start and pause timer:-
private void startTimer() {
isPause = false;
updateTime();
}
private void pauseTimer() {
isPause = true;
updateTime();
}
In AppUtil.java
public static String formattedTime(int totalSeconds) {
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
if (totalSeconds >= 3600) {
minutes = minutes + 60;
}
return String.format(Locale.US, "%02d:%02d", minutes, seconds);
}
Using the above solution my issue is resolved.
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 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
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++;
}