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
How to Use Scrollview in Android
Taking Picture from Camera Without Preview
Java.Lang.Runtimeexception: Unable to Instantiate Activity Componentinfo
Separate Back Stack For Each Tab in Android Using Fragments
How to Display a List View in an Android Alert Dialog
Failed to Resolve: Com.Google.Firebase:Firebase-Core:11.2.0
Android - How to Investigate an Anr
Warning: This Asynctask Class Should Be Static or Leaks Might Occur
Execution Failed App:Processdebugresources Android Studio
How to Add Stacktrace or Debug Option When Building Android Studio Project
Check If Application Is on Its First Run
Android Camera Intent: How to Get Full Sized Photo
How to Detect When an Android Application Is Running in the Emulator
How to Check If Alarmmanager Already Has an Alarm Set
Wait Firebase Async Retrieve Data in Android