I've wrote a small activity that is able to switch between two views. Now I am trying to add some animation (fade-in/fade-out effect). Can anybody explain me how to do that right?
My own attempt to do this works kinda buggy (if I will click buttons very fast, my application freezes). I use code listed below:
public class WelcomeActivity extends Activity {
private boolean isLogin = false;
private String KEY_IS_LOGIN = "KEY_IS_LOGIN";
private Animation anim_fadein;
private RelativeLayout welcome, login;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
welcome = (RelativeLayout)getLayoutInflater().inflate(R.layout.activity_welcome_menu, null);
login = (RelativeLayout)getLayoutInflater().inflate(R.layout.activity_welcome_login, null);
anim_fadein = AnimationUtils.loadAnimation(this, R.anim.anim_fadein);
if (savedInstanceState != null)
isLogin = savedInstanceState.getBoolean(KEY_IS_LOGIN, false);
if (isLogin)
setContentView(login);
else
setContentView(welcome);
}
#Override
public void onBackPressed() {
if (isLogin) {
setContentView(welcome);
welcome.startAnimation(anim_fadein);
isLogin = false;
} else {
super.onBackPressed();
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_IS_LOGIN, isLogin);
super.onSaveInstanceState(outState);
}
public void onButton1Click(View v) {
setContentView(login);
login.startAnimation(anim_fadein);
}
public void onButtonLoginClick(View v) {
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
}
public void onButtonBackClick(View v) {
setContentView(welcome);
welcome.startAnimation(anim_fadein);
}
Animation XML file:
<?xml version="1.0" encoding="utf-8"?>
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="800" />
Thanks in advance!
The way I have done this in the past is by using the ViewFlipper class and utilizing the built-in animation functions that the package provides.
Here is an example on how to do this; in my experience the transitions have been very smooth:
The XML File
<LinearLayout
//Ommitted...
<ViewFlipper
android:id="#+id/[your_id_here]"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
<!--Your first layout XML here...-->
</RelativeLayout>
<RelativeLayout
<!--Your second layout XML here...-->
</RelativeLayout>
</ViewFlipper>
</LinearLayout>
Please note that you do not have to use relative layouts, I simply used them for the sake of clarity.
Implementing The Animations
Get a reference to the ViewFlipper in your activity:
ViewFlipper v = (ViewFlipper) findViewById(R.id.[your_id]);
Set the animations as necessary:
v.setInAnimation(AnimationUtils.loadAnimation([your_activity_name].this, R.anim.[your_in_animation here]));
v.setOutAnimation(AnimationUtils.loadAnimation([your_activity_name].this, R.anim.[your_out_animation here]));
Please note that you can find some really good prebuilt animations in the Android class files located in the following directory:
[android-sdks]/samples/android-[VERSION_NUMBER_HERE]/ApiDemos/res/anim
I highly recommend using these if you can - it will save you much time.
Now, if you wish to switch between the views, use the following commands:
v.showNext();
v.showPrevious();
You might have to change the animation files slightly to make sure the animations transition properly (i.e. make a fade right and left animation).
Hope this helps!
I think there are 2 main solution to this problem
The first one is using a ViewFlipper as suggested.
The other one is to go with the solution described here.
I prefer the second one cause it doesn't need additional View object in your view hiearchy and second you can have your 2 view all across the view tree. Not only in a single place defined by the position of the ViewFlipper.
The following Method implements cross-fade between two views:
public void CrossFade(View v1, View v2)
{
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new DecelerateInterpolator()); //add this
fadeOut.setDuration(1000);
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); //add this
fadeIn.setDuration(1000);
fadeIn.setStartOffset(500);
fadeIn.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
v2.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animation animation) {
v2.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
fadeOut.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
v1.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animation animation) {
v1.setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
v1.startAnimation(fadeOut);
v2.startAnimation(fadeIn);
}
In the code above, v1 will fade-out and v2 will fade-in, you can change duration and offset according to your needs
Related
I am simply translating a cardview that contains an image and textview, horizontally from outside the screen, to inside.
here is my animation xml which is referenced using android:layoutAnimation of the cardview xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-300"
android:toXDelta="0"
android:fromYDelta="0"
android:toYDelta="0"
android:duration="1000"/>
</set>
I want the card to maintain its look and animate as a whole from one point to another, but instead I get a weird delay between the card and its contained views making for an ugly animation, the below image is my best attempt to describe it visually:
Any help would be greatly appreciated!
I have done like this
ObjectAnimator settleAnimator;
if(settleAnimator==null){
settleAnimator = ObjectAnimator.ofFloat(yourView, "translationX", 0);
settleAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
inAnimation = true;//just a boolean
}
#Override
public void onAnimationEnd(Animator animation) {
inAnimation = false;
}
#Override
public void onAnimationCancel(Animator animation) {
inAnimation = false;
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
}
settleAnimator.setDuration(200);//millisec
//this will take start value and end value in pixels ie. (from, to)
settleAnimator.setFloatValues(+300, 0);
settleAnimator.start();
}
The problem was that while I was testing different ways of doing this I left both the programmatic code and the xml code in, thus causing strange doubled up animations.
So I start my activity and then
setContentView(R.layout.myxmllayoutfile);
All is well, but I want to make my imagebutton suddenly grow (scale) from nothing (ie 1%). However the layout is already displaying the button so it suddenly disappears then grows back rather than growing from nothing.
I have some alternatives but is there a real solution?:
1. flying the imagebutton animate in from offscreen? ; or
2. making it tiny in the xml and then growing it, then if necessary changing the clickable area?; or
3. is there a better solution?
UPDATE:
As suggested I tried:
<ImageButton
android:id="#+id/spinner"
android:scaleType="fitXY"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="#drawable/clear"
android:orientation="horizontal"
android:visibility="invisible"
android:src="#drawable/spin"
/>
and in my java:
scaleView.startAnimation(scanimation);
ImageButton spinnerbutton=(ImageButton)findViewById(R.id.spinner);
spinnerbutton.setVisibility(View.VISIBLE);
but it is still visible before it shrinks to 1% then grows! Suggestions welcome.
UPDATE2:
Nothing has changed with the edited below code:
public void growit() {
final ImageView scaleView = (ImageView) findViewById(R.id.spinner);
Animation scanimation = AnimationUtils.loadAnimation(this, R.anim.throbbing2);
scanimation.setFillAfter(true);
scanimation.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation a) { Log.e("growit", "---- animation start listener called");
scaleView.setVisibility(View.VISIBLE);
}
public void onAnimationRepeat(Animation a) {
}
public void onAnimationEnd(Animation a) {
}
});
scaleView.startAnimation(scanimation);
}
Make imagebutton hidden.
Then in your animation set Animation listener and on start animation callback method set the button visible
UPDATE:
Animation animation = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mImageButton.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) { }
#Override
public void onAnimationEnd(Animation animation) { }
});
mImageButton.startAnimation(animation);
No permanent solution. Just used a workaround of making it tiny in the xml and then growing it as suggested in the question as a possible "solution"/workaround but not ideal.
How to animate different set of objects in different time duration one after the other?
JAVA Code:
ImageButton home = (ImageButton)findViewById(R.id.homeicon);
ImageButton settings = (ImageButton)findViewById(R.id.settingsicon);
Animation alpha_anim = AnimationUtils.loadAnimation(this, R.anim.alpha);
home.startAnimation(alpha_anim);
settings.startAnimation(alpha_anim);
Animation File:
<?xml version="1.0" encoding="utf-8"?>
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="0.9"
android:duration="8000" />
can anyone help me?
I had one screen where I need to animate first layout and as soon as its finish, I wanted to start animation on second layout.
So I had used handler at that time to do so, like this
Handler handler = new Handler(); // create Handler object
handler.post(homeRun);
Runnable homeRun = new Runnable() { // create runnable to start home anim
public void run() {
home.startAnimation(alpha_anim);
handler.postDelayed(settingsRun, 1000); // start setting anim after the time the home takes to animate
}
};
Runnable setingsRun = new Runnable() { // runnable to start settings anim
public void run() {
settings.startAnimation(alpha_anim);
}
};
You can add a delay to the second animation for the amount of time the first should take. Please realize that this may not be exact enough for you needs, if not then you might need to go the route of an AnimationListener
home.startAnimation(alpha_anim);
alpha_anim.setStartOffset(8000);
settings.startAnimation(alpha_anim);
If you want to perform one after the other you can use this code. BY using listener you are sure that animation is finished.
animation.setDuration(8000);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
animation.setDuration(6000);
animation.setAnimationListener(null);
settings.startAnimation(animation);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationStart(Animation animation) {
}
});
home.startAnimation(alpha_anim);
I'm trying to set up 2 layouts - I want one layout to slide up, and when it's finished another layout should fade in.
I've managed to get it working, but at the end of the two animation and first layout blinks once.
How can I solve it?
Here's the code(first layout is named titleLay and the second one is called registerLayout)-
final TranslateAnimation slide = new TranslateAnimation(0, 0, 0,-100 );
slide.setDuration(500);
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) {
RelativeLayout registerLayout = (RelativeLayout) findViewById(R.id.registerLay);
Animation fadeInAnimation = AnimationUtils.loadAnimation(con, R.anim.fade_in_anim);
registerLayout.startAnimation(fadeInAnimation);
registerLayout.setVisibility(View.VISIBLE);
}
});
titleLay.startAnimation(slide);
And that's the XML code of the R.anim.fade_in_anim-
<?xml version="1.0" encoding="UTF-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:interpolator="#android:anim/accelerate_interpolator"
android:duration="500"/>
</set>
Edit: If I use other types of animations(fade out, slide etc...) it works fine, without flicking.
Thanks!
If you are using animateLayoutChanges in your layout file in combination with the animation onAnimationEnd toggling the View visibility it will result in two animations running and the view flashing or blinking. Setting view visibility causes the layouts animateLayoutChanges to run and to fade the view in once and then the animation you created causes a second animation to run as well.
Instead of setting the view's visibility, try to use the setAlpha function.
registerLayout.setAlpha(0f); //invisible
registerLayout.setAlpha(1f); //visible
Remove the declerations and initilizations from your onAnimationEnd, the initilization may take a long time since the XML needs to be parsed from resources,
put thouse two lines in your onCreate:
RelativeLayout registerLayout = (RelativeLayout) findViewById(R.id.registerLay);
Animation fadeInAnimation = AnimationUtils.loadAnimation(con, R.anim.fade_in_anim);
and set visibility to slide:
final TranslateAnimation slide = new TranslateAnimation(0, 0, 0,-100 );
slide.setDuration(500);
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) {
registerLayout.startAnimation(fadeInAnimation);
registerLayout.setVisibility(View.VISIBLE);
}
});
titleLay.startAnimation(slide);
titleLay.setVisibilty(View.VISIBLE);
I have a simple LinearLayout with two Buttons side by side. They are supposed to slide into and out of view from the right side of the screen when needed. I have the animation working and the rest of the work is done, but I have one last problem to solve.
How can I set the LinearLayout's visibility to View.GONE after the slide out animation is complete? I need it to disappear once it's of screen.
Grab a reference of your Animation object doing the animation. Call Animation#setAnimationListener and in the listener's onAnimationEnd method set the visibility to View.GONE.
Duplicate : https://stackoverflow.com/a/7606533/3717188
anim.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationStart(Animation arg0) {
}
#Override
public void onAnimationRepeat(Animation arg0) {
}
#Override
public void onAnimationEnd(Animation arg0) {
}
});
LinearLayout al = (LinearLayout) findViewById(R.id.layoutid);
al.setVisibility(view.INVISIBLE);
Add the above code in your
onAnimationEnd(){
}