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.
Related
I have an imageview with 5 backgrounds to choose from. I want to fade image2 out and set image5 as background with fade in effect. This should keep changing randomly. The problem is, how do i do this efficiently?
this is how i give fade in and fade out effects using system animations-
fade out
Animation out = AnimationUtils.makeOutAnimation(this, true);
viewToAnimate.startAnimation(out);
viewToAnimate.setVisibility(View.INVISIBLE);
fade in
Animation in = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
viewToAnimate.startAnimation(in);
viewToAnimate.setVisibility(View.VISIBLE);
this is how i change my background-
search_engine_identifier.setImageResource(R.drawable.ic_yahoo);
Create two in xml you can get from here then load them like this.
ImageView myImageView = (ImageView) findViewById(R.id.imageView2);
Animation myFadeInAnimation = AnimationUtils.loadAnimation(Splash.this, R.anim.fadein)
Animation myFadeOutAnimation = AnimationUtils.loadAnimation(Splash.this, R.anim.fadeout);
int value = 0; // Global Type
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(value%2 == 0){
doFadeOutAnimation();
}else{
doFadeInAnimation();
}
value ++;
}
});
Another way to do this is by using one of Android's View Animator classes, such as ObjectAnimator. Here's what I'm doing:
1) Add the drawable ID's of the images you want to use into an int array.
2) Create ObjectAnimators for the fadeIn and fadeOut animations. You can set the duration of the fade in and fade out to whatever you want.
3) Add an AnimatorListener to the fadeOut ObjectAnimator so that when it finishes, it will set the new image (which is chosen randomly by selecting a random number from the images array) and then it will fade back in with the new image, using the fadeIn ObjectAnimator.
4) Create a runnable and in it's run method, start the fadeOut animation.
5) Call handler.postDelayed on the runnable and use that to decide how long you want each image to stay before fading out.
6) At the end of your Runnable's run method, call handler.postDelayed again so the images will continue to fade in and out, but you should make sure that you have some kind of conditional statement so that you can stop the animation when you need to, which is why I used the boolean "running" so I can set it to false when I need to stop the handler from looping.
ImageView mImageView = (ImageView) findViewById(R.id.imageView);
boolean running = true;
final int[] images = {R.drawable.image1, R.drawable.image2, R.drawable.image3,
R.drawable.image4, R.drawable.image5};
final Random random = new Random();
final Handler handler = new Handler();
final ObjectAnimator fadeIn = ObjectAnimator.ofFloat(mImageView, "alpha", 0f, 1f);
fadeIn.setDuration(1000);
final ObjectAnimator fadeOut = ObjectAnimator.ofFloat(mImageView, "alpha", 1f, 0f);
fadeOut.setDuration(1000);
fadeOut.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
int rand = random.nextInt(images.length);
mImageView.setImageResource(images[rand]);
fadeIn.start();
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
Runnable runnable = new Runnable() {
#Override
public void run() {
fadeOut.start();
if (running) {
handler.postDelayed(this, 5000);
}
}
};
handler.postDelayed(runnable, 5000);
}
This will continuously loop through your selected images (randomly) with fade in/ fade out animations. You can add a few checks to make sure the same image doesn't appear twice in a row, etc.
I'm trying to slide in a view on a RelativeLayout via an animation. Once the view is in place I have to alter the layout params of layout so that the new view doesn't block existing content. I call the code to update the layout after the animation but it occurs before the animation causing a block of area to be blank during the animation.
The following screens are before animation, during and after:
Here is the code. The relative layout is adjusted in onShowAd.
float fromY = getAdHeight();
float toY = 0;
TranslateAnimation slide = new TranslateAnimation(0,0,fromY,toY);
slide.setDuration(ANIMATION_RATE);
slide.setFillAfter(true);
mAdLayout.startAnimation(slide);
onShowAd();
mAdLayout.setVisibility(View.VISIBLE);
I tried differing orders of calling visible and other things as well as using a handler to postDelayed onShowAd() to wait the same amount of time as the ANIMATION_RATE however what happened you'd stare at the black box for the time it was post delayed and then have to wait for the animation so it was worse. In windows there's an API call LOCKWINDOWUPDATE that I could pass in a window handle to prevent updating...is there anything equivalent for a view in Android? Or any other ideas?
Incidentally when sliding the view OUT it works fine. Here is the code going the other way. onHideAd is where the layoutparams are modified in this one.
float toY = ((View) mAdLayout.getParent()).getBottom();
float fromY = 0;//toY - mAdLayout.getHeight();
TranslateAnimation slide = new TranslateAnimation(0,0,fromY,toY);
slide.setDuration(ANIMATION_RATE);
slide.setFillAfter(true);
mAdLayout.startAnimation(slide);
mAdLayout.setVisibility(View.GONE);
onHideAd();
Thanks for any suggestions!
EDIT: I added the listener and that doesn't take care of it. I have isolated it to the following code which in in the "onShowAd()" routine:
RelativeLayout.LayoutParams params = (android.widget.RelativeLayout.LayoutParams) mainFragmentContainer.getLayoutParams();
params.addRule(RelativeLayout.ABOVE, mAdLayout.getId());
mainFragmentContainer.setLayoutParams(params);
I've tried to further separate it by calling it with a handler.postDelayed and it seems like anywhere I place it in the chain of events causes it to occur BEFORE the animation itself shows. Very odd! :-(
This is the updated showAd routine. I tried reordering some of the calls as well.
float fromY = getAdHeight();
float toY = 0;
TranslateAnimation slide = new TranslateAnimation(0,0,fromY,toY);
slide.setDuration(ANIMATION_RATE);
slide.setFillAfter(true);
slide.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
onShowAd();
}
});
mAdLayout.setVisibility(View.VISIBLE);
mAdLayout.startAnimation(slide);
You should use an AnimationListener to accomplish what you are looking for. The problem you are running into is caused because the call to start animation returns instantly even though the animation doesn't complete for the time set to ANIMATION_RATE.
Ex for slide in:
float fromY = getAdHeight();
float toY = 0;
TranslateAnimation slide = new TranslateAnimation(0,0,fromY,toY);
slide.setDuration(ANIMATION_RATE);
slide.setFillAfter(true);
slide.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
onShowAd();
}
});
mAdLayout.setVisibility(View.VISIBLE);
mAdLayout.startAnimation(slide);
What i want is that each animation, from the code below, to start with a delay, like a sequence. So i have this code:
public void setAnimation(){
View view;
String animation = prefs.getString("animations", "Scale");
String interpolator = prefs.getString("interpolators", "Bounce");
Animation animate = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.scale_in);
for(int i=0; i<gridView.getChildCount(); i++){
view = gridView.getChildAt(i);
view.startAnimation(animate);
}
}
because there is a for loop, all child animations will start instantly. I already tried with:
Thread.sleep....
Handler...
animate.setStartTime...
animate.setStartOffset...
but all child animations starts instantly.
I tried this method inside of loop, and the animations won't start:
animate.setAnimationListener(new AnimationListener(){
public void onAnimationEnd(Animation arg0) {
view.startAnimation(animate);
}
public void onAnimationRepeat(Animation arg0) {
}
public void onAnimationStart(Animation arg0) {
}
});
Thanx in advance.
The solution is to create a GridLayoutAnimationController or LayoutAnimationController.
I used LayoutAnimationController to show elements in LinearLayout with animation effect one by one using following code.
Animation fadeIn = AnimationUtils.loadAnimation(context, R.anim.anim_fade_in);
//lnrContactContainer is LinearLayout.
AnimationSet set = new AnimationSet(true);
set.addAnimation(fadeIn);
set.setDuration(500);
controller = new LayoutAnimationController(set, 1f);
lnrContactContainer.setLayoutAnimation(controller);
lnrContactContainer.setVisibility(View.VISIBLE);
But same approach does not work when I use it to show fadeout animation while hiding LinearLayout lnrContactContainer.setVisibility(View.GONE);
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);
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.