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.
Related
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)
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);
I am confused with a problem:
Animation animation = new TranslateAnimation(0, 0, 200, 0);
animation.setDuration(800);
animation.setFillAfter(true);
btnView.startAnimation(animation);
btnView.setVisibility(View.VISIBLE);
I run this code work right but when I add the below code:
btnView.clearAnimation();
The animation can't show, how to clear animation after this?
if you want to clear the animations for the view once the animations i finished
you have to override Animation Listener of view and then clear the animation
if you want your view to move back to intial postion just setFillafter(false);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// TODO set params of the view to required position
}
});
To clear animation after it is finished set setFillAfter to false.
use this way:
// start animation
TranslateAnimation anim = new TranslateAnimation( 0, 100 , 0, 100);
anim.setDuration(1000);
anim.setFillAfter( true );
view.startAnimation(anim);
// end animation or cancel that
view.getAnimation().cancel();
view.clearAnimation();
cancel()
Cancel the animation. Canceling an animation invokes the animation
listener, if set, to notify the end of the animation.
If you cancel an animation manually, you must call reset()
before starting the animation again.
clearAnimation()
Cancels any animations for this view.
I am making a picture gallery app. I current have a imageview with a text view at the bottom. Currently it is just semitransparent. I want to make it fade in, wait 3 second, then fade out 90%. Bringing focus to it or loading a new pic will make it repeat the cycle. I have read thru a dozen pages and have tried a few things, no success. All I get is a fade in and instant fade out
protected AlphaAnimation fadeIn = new AlphaAnimation(0.0f , 1.0f ) ;
protected AlphaAnimation fadeOut = new AlphaAnimation( 1.0f , 0.0f ) ;
txtView.startAnimation(fadeIn);
txtView.startAnimation(fadeOut);
fadeIn.setDuration(1200);
fadeIn.setFillAfter(true);
fadeOut.setDuration(1200);
fadeOut.setFillAfter(true);
fadeOut.setStartOffset(4200+fadeIn.getStartOffset());
Works perfectly for white backgrounds. Otherwise, you need to switch values when you instantiate AlphaAnimation class. Like this:
AlphaAnimation fadeIn = new AlphaAnimation( 1.0f , 0.0f );
AlphaAnimation fadeOut = new AlphaAnimation(0.0f , 1.0f );
This works with black background and white text color.
Kotlin Extension functions for Guy Cothal's answer:
inline fun View.fadeIn(durationMillis: Long = 250) {
this.startAnimation(AlphaAnimation(0F, 1F).apply {
duration = durationMillis
fillAfter = true
})
}
inline fun View.fadeOut(durationMillis: Long = 250) {
this.startAnimation(AlphaAnimation(1F, 0F).apply {
duration = durationMillis
fillAfter = true
})
}
That's the solution that I've used in my project for looping fade-in/fade-out animation on TextViews:
private void setUpFadeAnimation(final TextView textView) {
// Start from 0.1f if you desire 90% fade animation
final Animation fadeIn = new AlphaAnimation(0.0f, 1.0f);
fadeIn.setDuration(1000);
fadeIn.setStartOffset(3000);
// End to 0.1f if you desire 90% fade animation
final Animation fadeOut = new AlphaAnimation(1.0f, 0.0f);
fadeOut.setDuration(1000);
fadeOut.setStartOffset(3000);
fadeIn.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationEnd(Animation arg0) {
// start fadeOut when fadeIn ends (continue)
textView.startAnimation(fadeOut);
}
#Override
public void onAnimationRepeat(Animation arg0) {
}
#Override
public void onAnimationStart(Animation arg0) {
}
});
fadeOut.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationEnd(Animation arg0) {
// start fadeIn when fadeOut ends (repeat)
textView.startAnimation(fadeIn);
}
#Override
public void onAnimationRepeat(Animation arg0) {
}
#Override
public void onAnimationStart(Animation arg0) {
}
});
textView.startAnimation(fadeOut);
}
Hope this could help!
You can use an extra animation object (which doesn't modify its alpha) to prevent the instant fade out, set animationListener for your fade-in effect and start the extra animation object in the on animationEnd of the fade-in, then you start fade-out on animation end of the extra animation object, try the link below, it'll help..
Auto fade-effect for textview
I was searching for a solution to similar problem (TextView fade in/wait/fade out) and came up with this one (in fact, the official docs point to this too). You can obviously improve this by adding more params.
public void showFadingText(String text){
txtView.setText(text);
Runnable endAction;
txtView.animate().alpha(1f).setDuration(1000).setStartDelay(0).withEndAction(
endAction = new Runnable() {
public void run() {
txtView.animate().alpha(0f).setDuration(1000).setStartDelay(2000);
}
}
);
}
Provided you have txtView declared somewhere else with alpha starting at zero.
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);