Android Fragments and Animation

Android Fragments and animation

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>

Transition animation between fragment

Google released the new Navigation UI library

So, now we can do the same fragment transitions from a your_named_navigation.xml resource (main > res > navigation > your_named_navigation.xml),

this an snippet code of my implementation:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@+id/first_fragment">

<fragment
android:id="@+id/first_fragment"
android:name="com.yourpackage.FirstFragment"
android:label="@string/title_first"
tools:layout="@layout/fragment_first">

<action
android:id="@+id/second_fragment_action"
app:destination="@id/second_fragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />

</fragment>

<fragment
android:id="@+id/second_fragment"
android:name="com.yourpackage.SecondFragment"
android:label="@string/title_second"
tools:layout="@layout/fragment_second">

<action ...next fragment/>

</fragment>

</navigation>

it also helps to handle clicks on back button and up button,

so, after have NavigationUi implementation in our proyect, we can call from our firstFragment instance the Navigation.findNavController method

myButton.setOnClickListener(View.OnClickListener {
//This opens our second fragment creating a stack of fragments
Navigation.findNavController(it).navigate(R.id.second_fragment_action)
})

The next Google's Codelab helped me, maybe can help you, greetings

Animate the transition between fragments

You need to use the new android.animation framework (object animators) with FragmentTransaction.setCustomAnimations as well as FragmentTransaction.setTransition.

Here's an example on using setCustomAnimations from ApiDemos' FragmentHideShow.java:

ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

and here's the relevant animator XML from res/animator/fade_in.xml:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/accelerate_quad"
android:valueFrom="0"
android:valueTo="1"
android:propertyName="alpha"
android:duration="@android:integer/config_mediumAnimTime" />

Note that you can combine multiple animators using <set>, just as you could with the older animation framework.


EDIT: Since folks are asking about slide-in/slide-out, I'll comment on that here.

Slide-in and slide-out

You can of course animate the translationX, translationY, x, and y properties, but generally slides involve animating content to and from off-screen. As far as I know there aren't any transition properties that use relative values. However, this doesn't prevent you from writing them yourself. Remember that property animations simply require getter and setter methods on the objects you're animating (in this case views), so you can just create your own getXFraction and setXFraction methods on your view subclass, like this:

public class MyFrameLayout extends FrameLayout {
...
public float getXFraction() {
return getX() / getWidth(); // TODO: guard divide-by-zero
}

public void setXFraction(float xFraction) {
// TODO: cache width
final int width = getWidth();
setX((width > 0) ? (xFraction * width) : -9999);
}
...
}

Now you can animate the 'xFraction' property, like this:

res/animator/slide_in.xml:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator"
android:valueFrom="-1.0"
android:valueTo="0"
android:propertyName="xFraction"
android:duration="@android:integer/config_mediumAnimTime" />

Note that if the object you're animating in isn't the same width as its parent, things won't look quite right, so you may need to tweak your property implementation to suit your use case.

swap fragment in an activity via animation

Old questiion and you probably already figured it out, but for future reference:

here's what you use to set a custom animation when you replace a fragment via code:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
ft.replace(R.id.fragment_container, newFragment, "fragment");
// Start the animated transition.
ft.commit();

Here is an example of the slide_in_left animation:

<?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="500"/>
</set>

Note that this is the animation if you are using the compatibility library. Instead if you are using and SDK with native support for the FragmentManager then your animation will look 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>

This is because the compatibility library does not support the new objectAnimator type and instead only implement the old animation framework.

replace two fragments with each other using animation

Here is the right solution:

FragmentTransaction fragmentTransactionSearch = getChildFragmentManager().beginTransaction();
fragmentTransactionSearch.add(childSearchFragment, "SEARCH");
fragmentTransactionSearch.replace(R.id.area_for_fragments, childSearchFragment);
fragmentTransactionSearch.commit();

Thats the start to place the first fragment into the defined <FrameLayout>

If you want to replace this childFragment with an other childFragment, then use:

FragmentTransaction fragmentTransactionDetail = getChildFragmentManager().beginTransaction();
fragmentTransactionDetail.setCustomAnimations(R.anim.slide_in_up, R.anim.slide_out_up, R.anim.slide_out_down, R.anim.slide_in_down);
fragmentTransactionDetail.remove(childSearchFragment);
fragmentTransactionDetail.add(childDetailFragment, "DETAIL");
fragmentTransactionDetail.replace(R.id.area_for_fragments, childDetailFragment);
fragmentTransactionDetail.addToBackStack("ShowDetail");
fragmentTransactionDetail.commit();

And as an Extra. If you want to control the BackButtonFunction, then you have to Overwrite the OnBackPressed function in the parentFragment with following code:

 if(parentFragment.getChildFragmentManager().getBackStackEntryCount() > 0)
{ this.getChildFragmentManager().popBackStack(); }

Animate fragment transition when showing and hiding (not replacing)

The same as you would animate replace transition. The only thing you should keep in mind - animate via method with 4 parameters:

public abstract FragmentTransaction setCustomAnimations(@AnimatorRes @AnimRes int enter, @AnimatorRes @AnimRes int exit, @AnimatorRes @AnimRes int popEnter,         @AnimatorRes @AnimRes int popExit);

Fragment transition animation vs fragment view rendering

It happens at the same time and you can't guarantee which one comes first. But if you have some view or some data in the destination fragment that is need to be there before the transition, you can call Fragment.postponeEnterTransition() in the entering fragment's onViewCreated(). For example if you are navigating from fragment A to B:

public class FragmentB extends Fragment {
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
...
postponeEnterTransition();
}
}

Once you've loaded the data and are ready to start the transition, call Fragment.startPostponedEnterTransition().



Related Topics



Leave a reply



Submit