I want to vibrate a view with scaleX and scaleY, and I am doing it with this code, but the problem is that sometimes the view is not correctly reset, and it shows with the scale applied...
I want that when the animation ends, the view must be seen with its original status always
this is the code:
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.9f);
scaleX.setDuration(50);
scaleX.setRepeatCount(5);
scaleX.setRepeatMode(Animation.REVERSE);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.9f);
scaleY.setDuration(50);
scaleY.setRepeatCount(5);
scaleY.setRepeatMode(Animation.REVERSE);
set.play(scaleX).with(scaleY);
set.start();
Thanks
For ValueAnimator and ObjectAnimator can be like this a try:
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
animation.removeListener(this);
animation.setDuration(0);
((ValueAnimator) animation).reverse();
}
});
UPDATE
On Android 7 it doesn't work.
Best way use the interpolator.
public class ReverseInterpolator implements Interpolator {
private final Interpolator delegate;
public ReverseInterpolator(Interpolator delegate){
this.delegate = delegate;
}
public ReverseInterpolator(){
this(new LinearInterpolator());
}
#Override
public float getInterpolation(float input) {
return 1 - delegate.getInterpolation(input);
}
}
In your code
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
animation.removeListener(this);
animation.setDuration(0);
animation.setInterpolator(new ReverseInterpolator());
animation.start();
}
});
According to the docs(Property Animation):
The property animation system can animate Views on the screen by changing the actual properties in the View objects. In addition, Views also automatically call the invalidate() method to refresh the screen whenever its properties are changed.
so you can use AnimatorListener to listen the animation event, then just reset the view property you animate. let's say cancel event and scaleX property:
scaleAnimator.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationCancel(Animator animation) {
scaleView.setScaleX(0)
}
});
Hope this can help a bit.
You can add an AnimatorListener, to be notified when the animation ends:
scaleY.addListener(new AnimatorListener() {
#Override
public void onAnimationEnd(Animator animation) {
// TODO Restore view
}
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
}
});
Related
I've set an Animation on ProgressBar in click event in Adapter
ObjectAnimator animation = ObjectAnimator.ofInt(holder.progressbar, "progress", 0, 100);
animation.setDuration(PROGRESS_TIME);
animation.setInterpolator(new DecelerateInterpolator());
animation.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
Toast.makeText(context,"HELL_Start",Toast.LENGTH_SHORT).show();
}
#Override
public void onAnimationEnd(Animator animator) {
//do something when the countdown is complete
Toast.makeText(context,"HELL_OFF_END",Toast.LENGTH_SHORT).show();
}
#Override
public void onAnimationCancel(Animator animator) {
Toast.makeText(context,"HELL_OFF_Cancel",Toast.LENGTH_SHORT).show();
}
#Override
public void onAnimationRepeat(Animator animator) { }
});
animation.start();
I'm trying to get Animation (when list item values get changed) from the ProgressBar by using
AlphaAnimation animation = (AlphaAnimation)mProgressBar.getAnimation();
but it is returning null
You can set the animator object as the associated view's tag.
holder.progressbar.setTag(animation);
Than retrieve it later:
ObjectAnimator animator = (ObjectAnimator) holder.progressBar.getTag();
// Do something with animator
I have a TextView in my activity, I would like to show the text, then fade out and hide it completely whenever the activity is started.
I have a wired situation, my code sometimes working (the TextView is fade out and gone), but most of times, it is not working (it could not reach the onAnimationEnd function).
Here is my code for it:
protected void onResume() {
fadeOut = new AlphaAnimation( 1.0f , 0.0f ) ;
fadeOut.setDuration(5000);
//fadeOut.setFillBefore(true);
fadeOut.setFillAfter(true);
//fadeOut.setStartOffset(1000);
fadeOut.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.d(TAG, "fade out start");
}
#Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "fade out end");
textRotateHint.setVisibility(View.INVISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
Log.d(TAG, "fade out repeat");
}
});
textRotateHint.setVisibility(View.VISIBLE);
textRotateHint.setText(R.string.rotation_hint);
textRotateHint.startAnimation(fadeOut);
super.onResume();
}
You can use a simple value animator.
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 0f);
valueAnimator.setDuration(5000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float alpha = (float) animation.getAnimatedValue();
mTextView.setAlpha(alpha);
}
});
valueAnimator.start();
Now I have to create an animation of a spinning fan. When user click POWER ON button, this fan begin to spin, then keep it's spinning speed at some level.When user click POWER OFF button, it slowing down then it stop.
I make some code as follows:
ImageView mFanImageview;
private ValueAnimator mFanValueAnimator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_centripetal_particle);
ButterKnife.bind(this);
}
private void startFan() {
mFanValueAnimator = new ValueAnimator();
mFanValueAnimator.setDuration(1000);
mFanValueAnimator.setFloatValues(mFanImageview.getRotation(), mFanImageview.getRotation() + 360);
mFanValueAnimator.setInterpolator(new AccelerateInterpolator());
mFanValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
mFanImageview.setRotation((Float) animation.getAnimatedValue());
}
});
mFanValueAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
mFanValueAnimator = new ValueAnimator();
mFanValueAnimator.setDuration(500);
mFanValueAnimator.setFloatValues(mFanImageview.getRotation(), mFanImageview.getRotation() + 360);
mFanValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
mFanValueAnimator.setRepeatMode(ValueAnimator.RESTART);
mFanValueAnimator.setInterpolator(new LinearInterpolator());
mFanValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
mFanImageview.setRotation((Float) animation.getAnimatedValue());
}
});
mFanValueAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationCancel(Animator animation) {
stopFanValueAnimator().start();
}
});
mFanValueAnimator.start();
}
#Override
public void onAnimationCancel(Animator animation) {
stopFanValueAnimator().start();
}
});
mFanValueAnimator.start();
}
private ValueAnimator stopFanValueAnimator() {
ValueAnimator stopAnimator = new ValueAnimator();
stopAnimator.setDuration(1000);
stopAnimator.setFloatValues(mFanImageview.getRotation(), mFanImageview.getRotation() + 360);
stopAnimator.setInterpolator(new DecelerateInterpolator());
stopAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
mFanImageview.setRotation((Float) animation.getAnimatedValue());
}
});
return stopAnimator;
}
#OnClick(R.id.stop_button)
public void onStopButtonClicked() {
mFanValueAnimator.cancel();
}
#OnClick(R.id.start_button)
public void onStartButtonClicked() {
startFan();
}
The animation above seems ok, but I found that the fan spinning speed at the end of AccelerateInterpolator animator is hard to match the beginning of LinearInterpolator.I have to adjust duration of LinearInterpolator animator carefully.
How can I get the update rate at the end of AccelerateInterpolator animator then set the right duration of LinearInterpolator animator?
I think the best approach is set accelerate interpolator initially, and on repeat again set LinearInterpolator. Now in case of repeat put a flag for handling switch off. If the switch off demanded then change value of switch Off flag that will apply Decelerate interpolator and make sure that the animation will not run again.
mFanValueAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationRepeat(Animator animation) {
if (switchOff) {
animation.setInterpolator(new DecelerateInterpolator());
} else {
animation.setInterpolator(new LinearInterpolator());
}
}
});
I'm translating a TextView 500dp to the right of the screen and then I use a listener to listen for the animation end where I want to change the text and then translate the TextView back to its initial space.
My code is :
ObjectAnimator animator = ObjectAnimator.ofFloat(rvDownCircle, "x", 500f);
animator.setStartDelay(500);
animator.setDuration(1500);
animator.start();
animator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
rvDownCircle.setText("New Label");
ObjectAnimator animator = ObjectAnimator.ofFloat(rvDownCircle, "x", 0);
animator.setDuration(1000);
animator.start();
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
The TextView is named rvDownCircle and as you can see when I'm on AnimationEnd I change the text to a new text - but what it happens is that text stays the same.
My question is : what am i doing wrong here and what should i change so when i reach the end of the animation setText will take effect.
I want to implement zoom feature on an ImageButton by Property Animation. For example, when I click the button, it will zoom out. And when I click it again, it will zoom in.
Here is part of my code:
OnClickListener clickPlayButtonHandler = new OnClickListener() {
#Override
public void onClick(View v) {
final ImageButton clickedButton = (ImageButton) v;
if((Boolean) v.getTag()) {
// zoom out
clickedButton.animate().setInterpolator(new AnticipateInterpolator()).setDuration(500).scaleXBy(-0.4f).scaleYBy(-0.4f).setListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
clickedButton.setImageResource(R.drawable.bg_pause);
System.out.println(clickedButton.getWidth()); // output the width of the button for checking
}
#Override
public void onAnimationEnd(Animator animation) {
clickedButton.setTag(false);
int d = clickedButton.getWidth();
System.out.println(clickedButton.getWidth());// output the width of the button for checking
}
#Override
public void onAnimationCancel(Animator animation) {}
#Override
public void onAnimationRepeat(Animator animation) { }
});
} else {
// process zoom in
}
}
};
I printed the width of the button before the animation start and the animation finished. However, I found they were the same. I thought when the zoom out animation finished the button width should be small than before. But it didn't.
Could not change view size by ViewPropertyAnimator?
There won't be changes in clickedButton.getWidth(), because the width of a view is not affected by scaling. You can think of getWidth() as a way to get unscaled width of a view. To change the width of a View requires a new measure/layout pass.
ViewPropertyAnimator doesn't change View's width/height or anything that could potentially trigger another layout pass. This is simply because layout passes are expensive and therefore could cause frame skipping, which is the last thing we want see during an Animation.
If you need to get scaled width of the button, you can do getScaleX() * clickedButton.getWidth()
Try the ObjectAnimator:
ObjectAnimator xAnimator =
ObjectAnimator.ofFloat(clickedButton, "scaleX", 1.0f, -0.4f);
ObjectAnimator yAnimator =
ObjectAnimator.ofFloat(clickedButton, "scaleY", 1.0f, -0.4f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.playTogether(xAnimator, yAnimator);
animatorSet.setInterpolator(new AnticipateInterpolator());
animatorSet.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
clickedButton.setImageResource(R.drawable.bg_pause);
System.out.println(clickedButton.getWidth());
}
#Override
public void onAnimationEnd(Animator animation) {
clickedButton.setTag(false);
int d = clickedButton.getWidth();
System.out.println(clickedButton.getWidth());
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
animatorSet.start();