I'm trying a simple example like having a TextView and translate it from 0% to 100% of the screen width
code is :
anim0 = ObjectAnimator.ofFloat(textViewId00, "translationX", -120f, 480f);
where 480f is the width of my screen.
What I want is the next N times ( n=5 for my example ) to add a delay before it starts.
I have tried to add the delay with setStartDelay() method on onAnimationRepeat but there is no effect.
My code is :
textViewId00 = (TextView) findViewById(R.id.textViewId00);
anim0 = ObjectAnimator.ofFloat(textViewId00, "translationX", -120f, 480f);
anim0.setDuration(2000);
anim0.setRepeatCount(5);
anim0.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
Log.i(TAG, "anim0 onAnimationStart ");
textViewId00.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animator animation) {
Log.i(TAG, "anim0 onAnimationEND " );
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
Log.i(TAG, "anim0 onAnimation REPEAT " );
anim0.setStartDelay(14000);
}
});
anim0.start();
The textView appears to the screen, moves until it disappears and then again from start without any delay.
I have just tried it using this code and it looks like it is doing what you want it to:
public void animateView() {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
final int screenWidth = size.x;
final ObjectAnimator anim0 = ObjectAnimator.ofFloat(textviewId00, "translationX", -120f, screenWidth);
anim0.setDuration(2000);
anim0.addListener(new Animator.AnimatorListener() {
int count;
#Override
public void onAnimationStart(Animator animation) {
textViewId00.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animator animation) {
if (++count < 5) {
anim0.setStartDelay(14000);
anim0.start();
}
}
#Override
public void onAnimationCancel(Animator animation) {}
#Override
public void onAnimationRepeat(Animator animation) {}
});
anim0.start();
}
Related
I am trying to implement crossfade animation in RecyclerView items. There are two text views which are to be shown one after another with crossfade animation.
Like 1000ms showing TextViewOne -> 500ms to crossfade to TextViewTwo -> 1000ms showing TextViewTwo -> 500ms to crossfade to TextViewOne -> 1000ms showing TextViewOne -> so on...
Can somebody help me with some pointers on this? Thanks in advance.
On exploring multiple articles, I found a solution to this. below is the code snippet.
/**
* Setup crossfade animation on the views
*
* #param firstView First view
* #param secondView Second view
*/
private void setAnimations(#NonNull View firstView, #NonNull View secondView) {
int crossFadeDuration = 500;
int holdDuration = 1000;
ObjectAnimator fadeOutFirstView = ObjectAnimator.ofFloat(firstView, View.ALPHA, 1f, 0f);
fadeOutFirstView.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
firstView.setVisibility(View.GONE);
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
fadeOutFirstView.setInterpolator(new LinearInterpolator());
ObjectAnimator fadeOutSecondView = ObjectAnimator.ofFloat(secondView, View.ALPHA, 1f, 0f);
fadeOutSecondView.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
secondView.setVisibility(View.GONE);
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
fadeOutSecondView.setInterpolator(new LinearInterpolator());
ObjectAnimator fadeInFirstView = ObjectAnimator.ofFloat(firstView, View.ALPHA, 0f, 1f);
fadeInFirstView.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
firstView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
fadeInFirstView.setInterpolator(new LinearInterpolator());
ObjectAnimator fadeInSecondView = ObjectAnimator.ofFloat(secondView, View.ALPHA, 0f, 1f);
fadeInSecondView.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
secondView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
fadeInSecondView.setInterpolator(new LinearInterpolator());
AnimatorSet mAnimationSetForward = new AnimatorSet();
mAnimationSetForward.setDuration(crossFadeDuration);
mAnimationSetForward.playTogether(fadeOutFirstView, fadeInSecondView);
AnimatorSet mAnimationSetReverse = new AnimatorSet();
mAnimationSetReverse.setDuration(crossFadeDuration);
mAnimationSetReverse.playTogether(fadeOutSecondView, fadeInFirstView);
mAnimationSetForward.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
mAnimationSetReverse.setStartDelay(holdDuration);
mAnimationSetReverse.start();
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
mAnimationSetReverse.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
mAnimationSetForward.setStartDelay(holdDuration);
mAnimationSetForward.start();
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
mAnimationSetForward.start();
}
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 put three ObjectAnimator into AnimatorSet ,when I cancel AnimatorSet or AnimatorSet finishes ,i need record the getAnimatedValue . But when I cancel the AnimatorSet, a ObjectAnimator maybe not had runned and i can call isRunning in onAnimationCancel but how do I judge this ObjectAnimator had runned at onAnimationEnd .
animatorSet.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
mSunMovPos = (float) sunAnimator.getAnimatedValue();
mCurSunSetColor = (int) sunSetAnimator.getAnimatedValue();
//How do judge nightAnimator had runned ?
mCurNightColor = (int) nightAnimator.getAnimatedValue();
}
#Override
public void onAnimationCancel(Animator animation) {
mSunMovPos = (float) sunAnimator.getAnimatedValue();
mCurSunSetColor = (int) sunSetAnimator.getAnimatedValue();
if (nightAnimator.isRunning())
mCurNightColor = (int) nightAnimator.getAnimatedValue();
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
I can't get the circular reveal animation to work.
I think I checked the most obvious things:
It starts, width and height are > 0 and it is visible, no Exception..
I load some data from the internet and display it in the view(fab)
The animation should only play after the download finishes.
TmdbHelper helper = new TmdbHelper();
helper.getMovieById(id, "en", new TmdbHelper.ResultListener() {
#Override
public void onResultReceived(JSONObject result) {
// called when finished downloading
try {
String rating = result.getString("vote_average");
AnimationHelper.circularReveal(fab, 500, 0);
fab.setText(rating);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
AnimationHelper:
public static void circularReveal(final View view, final long duration, long startDelay) {
// get the center for the clipping circle
int cx = (view.getLeft() + view.getRight()) / 2;
int cy = (view.getTop() + view.getBottom()) / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(view.getWidth(), view.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(view, cx, cy, 0, finalRadius);
anim.setDuration(duration);
anim.setStartDelay(startDelay);
anim.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
view.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {}
});
// make the view visible and start the animation
anim.start();
}
I use the circular reveal animation in other parts like this to make sure the view is attached, and it works:
headerContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
headerContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
AnimationHelper.circularReveal(headerContainer, 500, 200);
}
});
Perhaps you should erase this line inside your onResultRecieved():
fab.setVisibility(View.VISIBLE);
My assumption is that your circular reveal method is working just fine. It is because of you have made the FAB visible before the animation even begin, you can't see it in action.
As an addition, those lines you've shown which is working doesn't have fab.setVisibility(View.VISIBLE) called anywhere in it.
1st Approach:
Try Transition Listener.
getWindow().getSharedElementExitTransition().addListener(new Transition.TransitionListener() {
#Override
public void onTransitionStart(Transition transition) {
}
#Override
public void onTransitionEnd(Transition transition) {
}
#Override
public void onTransitionCancel(Transition transition) {
}
#Override
public void onTransitionPause(Transition transition) {
}
#Override
public void onTransitionResume(Transition transition) {
}
});
2nd Approach: Try setting start delay and listener to the reveal animation and when animation starts then set the view visible
if (Build.VERSION.SDK_INT >= 21) {
Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, 0, finalRadius);
anim.setStartDelay(300);
anim.setDuration(1000);
anim.setInterpolator(new DecelerateInterpolator());
anim.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
viewRoot.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
anim.start();
}
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
anim.start();