I assume because you are asking how to animate the fragment in and out, that you are not using the Navigation Framework as that gives it for free. So let's assume you are not using that and dig into how you would accomplish this.
First we need to have a method somewhere to handle swapping the fragment. Let's make an Extension class. I am using Kotlin and Androidx in all examples
FragmentExt.kt
import android.app.Activity
import android.app.ActivityManager
import android.content.Context
import android.os.Bundle
import androidx.annotation.IdRes
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import <YOUR PROJECT R FILE>
/*
* Written by Sam Rosewall App Studio 35
*/
val Activity.activityManager: ActivityManager
get() = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
fun FragmentActivity.swapFragment(
fragContainerId: Int,
newFragment: Fragment?,
oldFragment: Fragment? = null,
bundle: Bundle? = null,
hideCurrentFrag: Boolean = false,
addToBackStack:Boolean = false
) {
if (newFragment == null || newFragment.isVisible) {
loge("swapFragment called on already visible fragment")
return
}
logv("swapFragment( ${newFragment.javaClass.simpleName} )")
val currentFragBundle = newFragment.arguments
if (currentFragBundle == null && bundle != null) {
newFragment.arguments = bundle
logv("current bundle is null, so setting new bundle passed in")
} else if (bundle != null) {
newFragment.arguments?.putAll(bundle)
logv("current fragment bundle was not null, so add new bundle to it")
}
//Ensure no pending transactions are paused or incomplete
val fragmentManager = supportFragmentManager
fragmentManager.executePendingTransactions()
val fragmentTransaction = fragmentManager.beginTransaction()
//Make sure the requested fragment isn't already on the screen before adding it
if (newFragment.isAdded) {
logv("Fragment is already added")
if (newFragment.isHidden) {
logv("Fragment is hidden, so show it")
fragmentTransaction.show(newFragment)
newFragment.onResume() // since we were hiding it, we call onResume to simulate foreground on fragment
oldFragment?.let {
if(hideCurrentFrag) {
logv("hideCurrentFlag = true, hiding current fragment $it")
fragmentTransaction.hide(it)
it.onPause() // since we are hiding it, we call onPause to simulate background on fragment
}else{
logv("hideCurrentFlag = false, removing current fragment $it")
fragmentTransaction.remove(it)
}
}
}else{
logv("Fragment is already visible")
}
}else if(oldFragment == null){
if (addToBackStack) {
fragmentTransaction.setCustomAnimations(R.anim.in_from_right_to_left, R.anim.out_to_left, R.anim.in_from_left_to_right, R.anim.out_to_right )
fragmentTransaction.addToBackStack(null)
}
logv("oldFragment = null, so Replacing active contents of container with Fragment ${newFragment.javaClass.simpleName}")
fragmentTransaction.replace(fragContainerId, newFragment)
}else{
logv("Fragment is not added, and there is existing fragment to remove, so adding to the screen ${newFragment.javaClass.simpleName}")
fragmentTransaction.add(fragContainerId, newFragment)
if(hideCurrentFrag) {
logv("hideCurrentFlag = true, hiding current fragment $oldFragment")
fragmentTransaction.hide(oldFragment)
oldFragment.onPause() // since we are hiding it, we call onPause to simulate background on fragment
}else{
logv("hideCurrentFlag = false, removing current fragment $oldFragment")
fragmentTransaction.setCustomAnimations(R.anim.in_from_right_to_left, R.anim.out_to_left, R.anim.in_from_left_to_right, R.anim.out_to_right )
fragmentTransaction.remove(oldFragment)
}
}
logv("committing swap fragment transaction")
fragmentTransaction.commit()
}
fun FragmentActivity.removeFragment(@IdRes fragContainerId: Int) {
val fragmentManager = supportFragmentManager
fragmentManager.findFragmentById(fragContainerId)?.let {
fragmentManager.executePendingTransactions()
val transaction = fragmentManager.beginTransaction()
transaction.remove(it)
transaction.commit()
}
}
Now of course you will need to add the animations that you are after to the anims directory.
res->anim->[add files here]
in_from_left_to_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="500"
android:fromXDelta="-100%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="0%" />
</set>
in_from_right_to_left.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="500"
android:fromXDelta="100%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="0%" />
</set>
out_to_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="500"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="100%"
android:toYDelta="0%" />
</set>
out_to_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="500"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="-100%"
android:toYDelta="0%" />
</set>
Now all that is left, is using it. You have many options such as passing in bundle arguments, deciding to hide/show instead of add/remove. (note* if you hide / show the animations may not work, but you don't lose a webview loaded or other downloaded views, so it's really up to your use case.
MainActivity.kt
private fun changeToMyFragment() {
if (myFragment == null) {
myFragment = MyFragment()
}
swapFragment(R.id.placeholder_framelayout, myFragment)
}
That's it, any time you want to change fragments, just use this method "swapFragment" and pass the fragment you want in. The other parameters are all optional for extra control if you need it.
I added in logs for added clarity for you to read and a remove fragment in case you just need it gone.
Think of this like an extension you just drop in any project and use as-is. You don't have to dig into it, this will handle what you are asking for.
Happy Coding!