I have encountered an issue with custom animations on SupportFragmentManager Transaction when switching fragments. The code I'm using was working with the deprecated FragmentManager, but given that it is deprecated in Android P, I'm using the support version.
val ft = supportFragmentManager.beginTransaction()
ft.setCustomAnimations(animationIn, animationOut)
ft.hide(mCurrentFragment!!)
ft.show(f)
ft.commit()
mCurrentFragment = f
The error is an NPE when a hide custom animation is specified:
Caused by: java.lang.NullPointerException
at android.support.v4.app.FragmentManagerImpl.completeShowHideFragment(FragmentManager.java:1725)
I did try setting animationOut to 0 to make it work, but the fragment transition does not look as good.
Update: These are the animation items:
animationIn
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together" >
<objectAnimator
android:interpolator="@android:interpolator/accelerate_cubic"
android:propertyName="x"
android:duration="300"
android:valueType="floatType"
android:valueFrom="-500"
android:valueTo="0"
android:startOffset="300" />
<objectAnimator
android:propertyName="alpha"
android:duration="300"
android:valueType="floatType"
android:valueFrom="0.3"
android:valueTo="1"
android:startOffset="300" />
</set>
animationOut
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together" >
<objectAnimator
android:propertyName="alpha"
android:duration="300"
android:valueType="floatType"
android:valueFrom="1"
android:valueTo="0"
android:startOffset="0"/>
</set>
Has anyone encountered this issue? Thanks.
This is the part of the FragmentManagerImpl class that the error occurs:
void completeShowHideFragment(final Fragment fragment) {
if(fragment.mView != null) {
FragmentManagerImpl.AnimationOrAnimator anim = this.loadAnimation(fragment, fragment.getNextTransition(), !fragment.mHidden, fragment.getNextTransitionStyle());
if(anim != null && anim.animator != null) {
anim.animator.setTarget(fragment.mView);
if(fragment.mHidden) {
if(fragment.isHideReplaced()) {
fragment.setHideReplaced(false);
} else {
final ViewGroup container = fragment.mContainer;
final View animatingView = fragment.mView;
// --- the NPE error occurs here
container.startViewTransition(animatingView);
anim.animator.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
container.endViewTransition(animatingView);
animation.removeListener(this);
if(fragment.mView != null) {
fragment.mView.setVisibility(8);
}
}
});
}
} else {
fragment.mView.setVisibility(0);
}
setHWLayerAnimListenerIfAlpha(fragment.mView, anim);
anim.animator.start();
} else {
if(anim != null) {
setHWLayerAnimListenerIfAlpha(fragment.mView, anim);
fragment.mView.startAnimation(anim.animation);
anim.animation.start();
}
int visibility = fragment.mHidden && !fragment.isHideReplaced()?8:0;
fragment.mView.setVisibility(visibility);
if(fragment.isHideReplaced()) {
fragment.setHideReplaced(false);
}
}
}
if(fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
this.mNeedMenuInvalidate = true;
}
fragment.mHiddenChanged = false;
fragment.onHiddenChanged(fragment.mHidden);
}