277

How should you implement the sort of sliding that for example the Honeycomb Gmail client uses?

Can TransactionManager handle this automatically by adding and removing the Fragments, it's kind of difficult to test this due to the emulator being a slideshow :)

Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97
alexanderblom
  • 8,632
  • 6
  • 34
  • 40

6 Answers6

395

To animate the transition between fragments, or to animate the process of showing or hiding a fragment you use the Fragment Manager to create a Fragment Transaction.

Within each Fragment Transaction you can specify in and out animations that will be used for show and hide respectively (or both when replace is used).

The following code shows how you would replace a fragment by sliding out one fragment and sliding the other one in it's place.

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);

DetailsFragment newFragment = DetailsFragment.newInstance();

ft.replace(R.id.details_fragment_container, newFragment, "detailFragment");

// Start the animated transition.
ft.commit();

To achieve the same thing with hiding or showing a fragment you'd simply call ft.show or ft.hide, passing in the Fragment you wish to show or hide respectively.

For reference, the XML animation definitions would use the objectAnimator tag. An example of slide_in_left might look something like this:

<?xml version="1.0" encoding="utf-8"?>
<set>
  <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="x" 
    android:valueType="floatType"
    android:valueFrom="-1280"
    android:valueTo="0" 
    android:duration="500"/>
</set>
Reto Meier
  • 96,655
  • 18
  • 100
  • 72
  • 58
    When i tried this it show *RuntimeException: Unknown animator name: translate*. – Labeeb Panampullan Feb 08 '11 at 10:16
  • 3
    Make sure the animations defined in slide_in_left and right are constructed using a set of objectAnimator definitions rather than the old animation definition. – Reto Meier Feb 09 '11 at 16:20
  • 1
    @Dave: Added an example to the answer. – Reto Meier Feb 27 '11 at 17:43
  • 7
    That helped a lot. I was on the right track but just didn't get all the way there. For the other readers, you could also have android:interpolator as an attribute, with your favorite one specified (such as "@android:interpolator/linear"). It defaults to "@android:interpolator/accelerate_decelerate". – Dave MacLean Feb 28 '11 at 00:44
  • 1
    This does not work with compatability api. Application will crash while trying to inflate objectAnimator on devices with api level < 11. – Alexey Oct 12 '11 at 13:09
  • what if one wants to apply a custom animation ? the way you apply for other views using startAnimation method – 2cupsOfTech Feb 15 '12 at 11:53
  • What if I want to translate from 0% to 100%? This was supported by the translate object, but I can't used the "old" animations with FragmentTransaction. Also if I use the objectAnimator, will it stil work when running on devices lower than API 11? – ffleandro Feb 29 '12 at 14:15
  • 6
    I'm targeting API Level 7 with the compatability APIs. Is there a way for me to animate Fragments? – sleep Mar 15 '12 at 21:55
  • 5
    @JarrodSmith you can try using a compatibility library like [NineOldAndroids](http://nineoldandroids.com/) to bring the Honeycomb API down to Eclair. – Mr. S Apr 28 '12 at 14:05
  • If you want to make a transition that works on both 2.x and 3.0+ you should first look here: http://stackoverflow.com/a/7892524/969325. – Warpzit Jul 12 '12 at 10:39
  • 1
    I can't get animation to start when I hide(). Works only on show – Jacek Kwiecień Dec 18 '12 at 13:26
  • @LabeebP, this only works when using the support library. See the following answer for more info: http://stackoverflow.com/a/9856449/435605 – AlikElzin-kilaka Apr 24 '13 at 17:02
  • I've added NineOldAndroids support to the Google Support library. See http://www.github.com/kedzie/Support_v4_NineOldAndroids for details. It allows using Property Animations for Fragment Transitions, PageTransformers, and some other stuff. – mark.kedzierski May 27 '13 at 03:31
  • `ObjectAnimator` causes an exception for me, whereas `translate` animation works fine. – Alireza Mirian Apr 04 '14 at 04:40
  • Nine Old doesn't work with fragment https://github.com/JakeWharton/NineOldAndroids/issues/43 – Dory Jan 09 '15 at 05:59
  • 1
    In case it helps others, if you want your animation to reverse when you back out of the fragment then specify all 4 parameters: ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right, R.anim.slide_in_right, R.anim.slide_out_left); – Justin Feb 06 '15 at 00:40
  • Please note that by using `fragmentTransaction.replace()`, you may be causing fragments to hit lifecycle events unnecessarily when the user presses the back button as compared to `fragmentTransaction.add()`. But, if you use `.add()`, you're not going to get as nice of an animation :) See here: http://stackoverflow.com/a/21684520/1738090 – w3bshark Jan 29 '16 at 03:20
  • Is there a built-in transition that is already used for activities, which I can use for fragments too? – android developer Jan 29 '20 at 15:34
259

If you don't have to use the support library then have a look at Roman's answer.

But if you want to use the support library you have to use the old animation framework as described below.

After consulting Reto's and blindstuff's answers I have gotten the following code working.

The fragments appear sliding in from the right and sliding out to the left when back is pressed.

FragmentManager fragmentManager = getSupportFragmentManager();

FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);

CustomFragment newCustomFragment = CustomFragment.newInstance();
transaction.replace(R.id.fragment_container, newCustomFragment );
transaction.addToBackStack(null);
transaction.commit();

The order is important. This means you must call setCustomAnimations() before replace() or the animation will not take effect!

Next these files have to be placed inside the res/anim folder.

enter.xml:

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

exit.xml:

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="-100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_enter.xml:

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="-100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_exit.xml:

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

The duration of the animations can be changed to any of the default values like @android:integer/config_shortAnimTime or any other number.

Note that if in between fragment replacements a configuration change happens (for example rotation) the back action isn't animated. This is a documented bug that still exists in the rev 20 of the support library.

Community
  • 1
  • 1
dmanargias
  • 2,626
  • 1
  • 13
  • 7
  • 50
    This just saved me. Note, pay attention to **the order is important**, which, naturally, I missed the first time. This means you must call setCustomAnimations() before replace(). – Stephen Kidson Dec 05 '13 at 20:01
  • 3
    I tried to implement on my fragments.I wrote everything as you mentioned but logcat says :unknow animator name translate How can I overcome this issue? By the way I'm calling my fragment on Navigation Drawer(Sliding Menu) – Zafer Celaloglu Nov 06 '14 at 11:36
  • Works great but it turns out that building this with build tools 21.1 generates an error saying "Invalid file name: must contain only lowercase letters and digits ([a-z0-9_.])". I suggest editing the filenames in the answer to pop_enter.xml and pop_exit.xml. – smichak Jan 25 '15 at 07:46
  • Great solution and it works great when i press the back button. I just have one question: If i want to create a custom backButton, what code should i call to replicate the behaviour from the back button? – Teilmann Mar 05 '15 at 08:01
  • 1
    Thomas if you want to back, you should implemented this form: .setCustomAnimations(R.anim.pop_enter, R.anim.pop_exit, R.anim.enter, R.anim.exit) – Alex Zaraos Jun 15 '15 at 15:41
  • @dmanargias, This is solution is working for me Too. I even tried slide up/ down and fade in/ out transition. But I'm getting a white screen, when the fragments are animating. This is happening only when I set animation. I tried with a dummy fragment, to check whether it is because of delay in view creation. But, white screen can be seen in this case too. Has anyone else faced similar issue – Sangeetha Pinto Dec 09 '16 at 10:50
28

I'd highly suggest you use this instead of creating the animation file because it's a much better solution. Android Studio already provides default animation you can use without creating any new XML file. The animations' names are android.R.anim.slide_in_left and android.R.anim.slide_out_right and you can use them as follows:

fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();              
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fragmentManager.addOnBackStackChangedListener(this);
fragmentTransaction.replace(R.id.frame, firstFragment, "h");
fragmentTransaction.addToBackStack("h");
fragmentTransaction.commit();

Output:

enter image description here

Toufic Batache
  • 762
  • 10
  • 24
Gowthaman M
  • 8,057
  • 8
  • 35
  • 54
  • 1
    android.R... "Android Studio Provides default animation",that's not for android studio it can work in eclipse too,android.R is android specific.And by the way you didn't share the information what apis have this.Because stuff on android.R are different on different apis. – Steve Moretz Feb 05 '19 at 09:15
  • @stevemoretz thaxs bro I agreed your point.. I will correct and update my answer... – Gowthaman M Feb 05 '19 at 09:48
5

My modified support library supports using both View animations (i.e. <translate>, <rotate>) and Object Animators (i.e. <objectAnimator>) for Fragment Transitions. It is implemented with NineOldAndroids. Refer to my documentation on github for details.

mark.kedzierski
  • 663
  • 4
  • 10
2

As for me, i need the view diraction:

in -> swipe from right

out -> swipe to left

Here works for me code:

slide_in_right.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

slide_out_left.xml

 <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="0" android:toXDelta="-50%p"
                android:duration="@android:integer/config_mediumAnimTime"/>
        <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
                android:duration="@android:integer/config_mediumAnimTime" />
    </set>

transaction code:

inline fun FragmentActivity.setContentFragment(
        containerViewId: Int,
        backStack: Boolean = false,
        isAnimate: Boolean = false,
        f: () -> Fragment

): Fragment? {
    val manager = supportFragmentManager
    return f().apply {
        manager.beginTransaction().let {
            if (isAnimate)
                it.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)

            if (backStack) {
                it.replace(containerViewId, this, "Fr").addToBackStack("Fr").commit()
            } else {
                it.replace(containerViewId, this, "Fr").commit()
            }
        }
    }
}
Serg Burlaka
  • 2,351
  • 24
  • 35
0

I solve this the way Below

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
fg.startAnimation(anim);
this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment