I have an activity with a fragment that needs to be animated when being created, but not when the orientation changes .
The fragment is being inserted into a layout dynamically, as it's a part of a navigation-drawer-style activity.
I wanted to avoid re-creating the fragment for configuration changes, so I used setRetainInstance in the fragment. It works, but for some reason the animation also restarts each time I rotate the device.
I've added this to the fragment:
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
and this to the activity:
final FragmentManager fragmentManager = getSupportFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyFragment fragment= (MyFragment) fragmentManager.findFragmentByTag(MyFragment.TAG);
if (fragment== null) {
fragmentTransaction.setCustomAnimations(R.anim.slide_in_from_left, R.anim.slide_out_to_right);
fragment= new MyFragment();
fragmentTransaction
.add(R.id.fragmentContainer, fragment, MyFragment.TAG).commit();
}
fragment_container.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
This solution works in general, but it causes bad things to the lifecycle you've tried to achieve :
MyFragment fragment= (MyFragment) fragmentManager.findFragmentByTag(MyFragment.TAG);
if (MyFragment== null) {
MyFragment= new MyFragment();
fragmentManager.beginTransaction().setCustomAnimations(R.anim.slide_in_from_left, R.anim.slide_out_to_right)
.replace(R.id.fragmentContainer, fragment, MyFragment.TAG).commit();
} else {
//workaround: fragment already exists, so avoid re-animating it by quickly removing and re-adding it:
fragmentManager.beginTransaction().remove(fragment).commit();
final Fragment finalFragment = fragment;
new Handler().post(new Runnable() {
@Override
public void run() {
fragmentManager.beginTransaction().replace(R.id.fragmentContainer, fragment, finalFragment .TAG).commit();
}
});
}
I would still want to see what can be done, because this can cause things you didn't want to occur(onDetach for the fragment, for example).
One way to solve this is to avoid adding the animation via the fragmentManager, and just do it for the view itself within the fragment lifecycle. This is how it looks like:
BaseFragment
@Override
public void onViewCreated(final View rootView, final Bundle savedInstanceState) {
super.onViewCreated(rootView, savedInstanceState);
if (savedInstanceState == null)
rootView.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_in_from_left));
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (!getActivity().isChangingConfigurations())
getView().startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.fade_out));
}
How about you override the onCreateAnimation()
method and prevent the animation from happening if the fragment is being recreated after a rotation?
As shown here: How to disable/avoid Fragment custom animations after screen rotation
EDIT: Here's a sample code:
BaseFragment.java
...
private boolean mNeedToAvoidAnimation;
@Override
public void onDestroyView() {
super.onDestroyView();
mNeedToAvoidAnimation = true;
}
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
// This avoids the transaction animation when the orienatation changes
boolean needToAvoidAnimation = mNeedToAvoidAnimation;
mNeedToAvoidAnimation = false;
return needToAvoidAnimation ? new Animation() {
} : super.onCreateAnimation(transit, enter, nextAnim);
}
This fragment should be the base one that all fragments in this activity will extend.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With