Android | Non-stop transition form an animation to an animatorSet - android

I am trying to make an combined animation where a view is first moved (TranslateAnimation) and then hidden/revealed (createCircularReveal Animator)(like here). Rigth now, I am accomplishing it by starting the animator after the animation with the onAnimationEnd callback. But the thing is, it does not start right away but is delayed for like half a second which makes it look less smooth.
Is this even the right aaproach to do this, or is there another way to create such an move + property animation?
Is there may be a way to adjust the onAnimationEnd callback so that it really start rigth away?
EDIT: here my final code:
...
final Animator circularReveal = ViewAnimationUtils.createCircularReveal(
....
);
circularReveal.setDuration(3500);
circularReveal.setInterpolator(new AnimationUtils().loadInterpolator(YourWorkouts.this,
android.R.interpolator.linear_out_slow_in));
circularReveal.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
createNewWorkoutDialogCardView.setVisibility(View.VISIBLE);
}
});
final Animator circularHide = ViewAnimationUtils.createCircularReveal(
...
);
circularHide.setDuration(600);
circularHide.setInterpolator(new AnimationUtils().loadInterpolator(YourWorkouts.this,
android.R.interpolator.linear_out_slow_in));
circularHide.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
Log.v("YourWorkouts", "onAnimationEnd: set FAB INVISIBLE");
createWorkoutFab.setVisibility(View.GONE);
}
});
final AnimatorSet animSet = new AnimatorSet();
animSet.playTogether(circularHide,circularReveal);
animSet.setStartDelay(300); // the animator waits only 0.3 seconds
Integer fabTranslationDistanceX = fabEndPositionX - (createNewWorkoutFABContainer.getLeft() + createNewWorkoutFABContainer.getWidth()/2);
Integer fabTranslationDistanceY = fabEndPositionY - createWorkoutFab.getHeight()/2 - (createNewWorkoutFABContainer.getTop() + createNewWorkoutFABContainer.getHeight()/2);
Log.v("YourWorkouts", "xDialogCenter" + fabTranslationDistanceX);
TranslateAnimation moveFAB = new TranslateAnimation(0, fabTranslationDistanceX, 0, fabTranslationDistanceY);
moveFAB.setDuration(500); // the translation takes 0.5 seconds
moveFAB.setFillAfter(true);
moveFAB.setInterpolator(new AnimationUtils().loadInterpolator(YourWorkouts.this,
android.R.interpolator.fast_out_linear_in));
animSet.start(); // start animator for property animation
createNewWorkoutFABContainer.startAnimation(moveFAB); // start animation to move view across the screen

you could try this:
anim1 will be the 1st animation, with a duration of 300 ms and anim2 will start after 300 ms
TranslateAnimation anim1 = new TranslateAnimation();
Animator anim2 = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
anim1.setDuration(300);
anim2.setDuration(300);
anim2.setStartOffset(300);

Related

Multiple ViewPropertyAnimators

Hope I am not duplicating a question here; I couldn't find one about multiple ViewPropertyAnimators. The goal is to have a view animate from y1 to y2 in 8 seconds. Fade in the first second, and then fade out on the last second.
Here is what I have Tried in my Activity's onCreate():
final View animatingView = findViewById(R.id.animateMe);
animatingView.post(new Runnable() {
#Override
public void run() {
//Translation
animatingView.setY(0);
animatingView.animate().translationY(800).setDuration(8000);
//Fading view in
animatingView.setAlpha(0f);
animatingView.animate().alpha(1f).setDuration(1000);
//Waiting 6 seconds and then fading the view back out
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
animatingView.animate().alpha(0f).setDuration(1000);
}
}, 6000);
}
});
However, the result is a translation from 0 to 800, and alpha from 0 to 1 all in one second. and then 6 seconds later the view fades out. It looks every time I call View.animate() it returns the same ViewPropertyAnimator. Is there a way I can have multiple of them? I was thinking about animating the view's alpha, nesting the view in a relative layout, and then animating the relative layouts translation. I would rather not go that route if I don't have to. Does anyone know of a better solution?
You can solve this by using ObjectAnimator instances directly, rather than using the .animate() abstraction.
ObjectAnimator translationY = ObjectAnimator.ofFloat(animatingView, "translationY", 0f, 800f);
translationY.setDuration(8000);
ObjectAnimator alpha1 = ObjectAnimator.ofFloat(animatingView, "alpha", 0f, 1f);
alpha1.setDuration(1000);
ObjectAnimator alpha2 = ObjectAnimator.ofFloat(animatingView, "alpha", 1f, 0f);
alpha2.setDuration(1000);
alpha2.setStartDelay(7000);
AnimatorSet set = new AnimatorSet();
set.playTogether(translationY, alpha1, alpha2);
set.start();

Object animator using old view position

I have a simple cardview topCard and want to translate it from the center of a layout to right side and back to the initial place.
Wrote some code using object animator:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(topCard, "translationX", topCard.getWidth() + 150);
objectAnimator.setDuration(1500);
objectAnimator.start();
objectAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animation) {
ObjectAnimator translationX = ObjectAnimator.ofFloat(topCard, "translationX", - (topCard.getWidth() + 150));
translationX.setDuration(1500);
translationX.start();
So, my view correctly translates to the right side and the second animation move it not to the start place but to the (start place - (topCard.getWidth() + 150)).
How can I animate translating view to the right and back to the same position using 2 sequence animations?
Here is wrong result that i have
https://i.imgur.com/8SShfHL.gifv
You should try putting this in your onAnimationEnd instead:
#Override
public void onAnimationEnd(Animator animation) {
ObjectAnimator translationX = ObjectAnimator.ofFloat(topCard, "translationX",
topCard.getWidth() + 150, - (topCard.getWidth() + 150));
translationX.setDuration(1500);
translationX.start();
Notice that I added topCard.getWidth() + 150, making that the starting position of the topCard. According to the ObjectAnimator.ofFloat Android Docs:
Constructs and returns an ObjectAnimator that animates between float values. A single value implies that that value is the one being animated to. Two values imply starting and ending values.

Have scale animation AFTER translate animation from last position

I want to apply a translate animation to the view from bottom right to center THEN scale animation from where it finished translation. Once this is done, I want the view to come back to its original size and position. Any idea how to do that? Here is the code I am using for animation
TranslateAnimation translateAnim = new TranslateAnimation(0, midScreenX, 0, midScreenY);
translateAnim.setDuration(2000);
ScaleAnimation scaleAnim = new ScaleAnimation(1, 4, 1, 4, Animation.RELATIVE_TO_SELF,1f, Animation.RELATIVE_TO_SELF,1f);
scaleAnim.setDuration(2000);
use an AnimationListener to chain the animations and use setFillAfter(true)
TranslateAnimation translateAnim = new TranslateAnimation(0, midScreenX, 0, midScreenY);
translateAnim.setDuration(2000);
// user setFillAfter to make sure that we scale from the last position it was animated to.
translateAnim.setFillAfter(true);
// make scaleAnim final so we can use it in the AnimationListener.onAnimationEnd method
final ScaleAnimation scaleAnim = new ScaleAnimation(1, 4, 1, 4, Animation.RELATIVE_TO_SELF,1f, Animation.RELATIVE_TO_SELF,1f);
scaleAnim.setDuration(2000);
scaleAnim.setFillAfter(true);
translateAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// now that the first animation is done, start the second
someViewObj.startAnimation(scaleAnim);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
// start first animation
someViewObj.startAnimation(translateAnim);
Android Docs : http://developer.android.com/reference/android/view/animation/Animation.AnimationListener.html
http://developer.android.com/reference/android/view/animation/Animation.html#setFillAfter(boolean)

android textview animation not smooth

I am trying to perform 2 text animations in a row with my TextView under Android
first:
TextView target = (TextView)findViewById(R.id.textanimation);
target.setText(text1);
target.startAnimation(animationSet1);
animationSet1 is a set of alpha and translate animations:
Animation alpha = new AlphaAnimation(0.0f, 1.0f);
Animation a = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, -1.0f,
Animation.RELATIVE_TO_SELF, 0);
alpha.setDuration( 1000 );
a.setDuration( 1000 );
When onAnimationEnd happens in animationSet1 I immediately start another animation
TextView target = (TextView)findViewById(R.id.textanimation);
target.setText(text2);
target.startAnimation(animationSet1);
However in the 2nd animation I can see on a split of second a fully opaque text, however it should start with 0 alpha. How to avoid this situation? Will appresiate any answer.
P.S. Even if I have 2 separate textviews with the prepared text in both - same bug is seen.
If I put some delay between the animations both of them become smooth.
Sergey
I'm not sure how you are triggering the start of the 2nd animation following the termination of the 1st animation. I'm guessing you're checking to see if the animation on a view is null. This isn't the best or correct way to do it. Instead you should you an AnimationListener
Animation animation1 = new Animation();//Replace with your animation
animation1.setDuration(DURATION_1);
animation1.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation arg0) {}
public void onAnimationRepeat(Animation arg0) {}
public void onAnimationEnd(Animation arg0) {
Animation animation2 = new Animation();
animation2.setDuration(DURATION_2);
view2.startAnimation(animation2);
}
});
view1.startAnimation(animation1);

Android alpha animation fadein fadeout with delays

I want to do a very simple alpha animation but I cannot find a valid way.
The idea is to perform this animation over a view:
alpha from 0 to 1 of 1 second
hold alpha at 1 for 5 seconds
alpha from 1 to 0 of 1 second
hold alpha at 0 for 5 seconds.
start again on 1.
I've tried to implement that with an AnimationSet as:
AnimationSet animationSet = new AnimationSet(true);
Animation animation1 = new AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
animation1.setDuration(1000);
Animation animation2 = new AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
animation2.setDuration(1000);
animation2.setStartOffset(5000);
Animation animation3 = new AlphaAnimation(0.0f, 0.0f);
animation3.setDuration(4000)
animation3.setStartOffset(6000);
animationSet.add(animation1);
animationSet.add(animation2);
animationSet.add(animation3);
etc..
but it seams that the third animation do a mess with all the alpha animations, I supose that this cause an internal incoherence in the way that Android manage this type of animation.
Any idea?
Thank you.
Ok Keep in mind these 2 points to solve this
If I want to animate 1.0f to 0.0f after 5 seconds with an animation duration of 1 seconds, this is ultimately a 1 second animation with a pause of 5 seconds.
To acheive this:
setDuration(1000) (it has a 1 second duration)
setStartOffset(5000) (it will start after 5 seconds)
You only need 2 animations that will loop forever.
1.0.0f to 1.0f with 5 seconds pause and 1 second duration
2.1.0f to 0.0f with 5 seconds pause and 1 second duration
And here is the code:
animation1 = new AlphaAnimation(0.0f, 1.0f);
animation1.setDuration(1000);
animation1.setStartOffset(5000);
animation2 = new AlphaAnimation(1.0f, 0.0f);
animation2.setDuration(1000);
animation2.setStartOffset(5000);
textView.startAnimation(animation1);
However to loop forever I will use AnimationListener because repeatCount is buggy:
animation1 = new AlphaAnimation(0.0f, 1.0f);
animation1.setDuration(1000);
animation1.setStartOffset(5000);
//animation1 AnimationListener
animation1.setAnimationListener(new AnimationListener(){
#Override
public void onAnimationEnd(Animation arg0) {
// start animation2 when animation1 ends (continue)
textView.startAnimation(animation2);
}
#Override
public void onAnimationRepeat(Animation arg0) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationStart(Animation arg0) {
// TODO Auto-generated method stub
}
});
animation2 = new AlphaAnimation(1.0f, 0.0f);
animation2.setDuration(1000);
animation2.setStartOffset(5000);
//animation2 AnimationListener
animation2.setAnimationListener(new AnimationListener(){
#Override
public void onAnimationEnd(Animation arg0) {
// start animation1 when animation2 ends (repeat)
textView.startAnimation(animation1);
}
#Override
public void onAnimationRepeat(Animation arg0) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationStart(Animation arg0) {
// TODO Auto-generated method stub
}
});
textView.startAnimation(animation1);
There is a simpler solution to this.
Lets assume that your view is in state GONE. To animate to its visibility:
yourView.setVisibility(View.VISIBLE);
yourView.animate().alpha(1).setDuration(300);
Through the same way you can add animation listeners.
This also works for scale and translation animations.
Try This
val shortAnimationDuration = 1000
yourView.apply {
alpha = 0f
animate()
.alpha(1f)
.setDuration(shortAnimationDuration.toLong())
.setListener(object :AnimatorListenerAdapter(){
override fun onAnimationEnd(animation: Animator?) {
//You can add what you want to do after completing animation
}
})
}
This is a Fade in animation. If you want Fade out you just swap the alpha values.

Categories

Resources