上次谈到了Fragment动画加载的异常问题,今天再聊聊它的动画加载loadAnimation的实现源代码:
Animation loadAnimation(Fragment fragment, int transit, boolean enter,
int transitionStyle) {
接下来具体看一下里面的源码部分,我将一部分一部分的讲解,首先是:
Animation animObj = fragment.onCreateAnimation(transit, enter,
fragment.mNextAnim);
if (animObj != null) {
return animObj;
}
开始的这部分,会调用Fragment的onCreateAnimation这个方法,在Fragment类中,这个方法为空,并没有现实:
/**
* Called when a fragment loads an animation.
*/
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
return null;
}
如果你写的Fragment子类在继承Fragment后重写了这个方法内容,就可以在这里面得到动画。
如果你没有重写这个方法,那就会往下继续:
if (fragment.mNextAnim != 0) {
Animation anim = AnimationUtils.loadAnimation(mActivity, fragment.mNextAnim);
if (anim != null) {
return anim;
}
}
fragment.mNextAnim这个就是在我们添加或者替换fragment的时候,用的FragmentTransaction设置的那个动画,如上篇文章中后面附的那个例子:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.animator.fragment_rotate_enter,
R.animator.fragment_rotate_exit,
R.animator.fragment_rotate_pop_enter,
R.animator.fragment_rotate_pop_exit);
具体是进入动画,还是退出动画,就要看当时的具体情况了,这个是不需要开发者操心的。
如果我们之前也没定义切换动画,那好吧,就要看我们是否设置transit和transitionStyle参数了:
if (transit == 0) {
return null;
}
int styleIndex = transitToStyleIndex(transit, enter);
if (styleIndex < 0) {
return null;
}
再看一下transitToStyleIndex方法:
public static int transitToStyleIndex(int transit, boolean enter) {
int animAttr = -1;
switch (transit) {
case FragmentTransaction.TRANSIT_FRAGMENT_OPEN:
animAttr = enter ? ANIM_STYLE_OPEN_ENTER : ANIM_STYLE_OPEN_EXIT;
break;
case FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
animAttr = enter ? ANIM_STYLE_CLOSE_ENTER : ANIM_STYLE_CLOSE_EXIT;
break;
case FragmentTransaction.TRANSIT_FRAGMENT_FADE:
animAttr = enter ? ANIM_STYLE_FADE_ENTER : ANIM_STYLE_FADE_EXIT;
break;
}
return animAttr;
}
所以,transit的值只能是:FragmentTransaction.TRANSIT_FRAGMENT_OPEN,FragmentTransaction.TRANSIT_FRAGMENT_CLOSE,FragmentTransaction.TRANSIT_FRAGMENT_FADE。然后,会根据这个值,调用系统自己的动画文件:
switch (styleIndex) {
case ANIM_STYLE_OPEN_ENTER:
return makeOpenCloseAnimation(mActivity, 1.125f, 1.0f, 0, 1);
case ANIM_STYLE_OPEN_EXIT:
return makeOpenCloseAnimation(mActivity, 1.0f, .975f, 1, 0);
case ANIM_STYLE_CLOSE_ENTER:
return makeOpenCloseAnimation(mActivity, .975f, 1.0f, 0, 1);
case ANIM_STYLE_CLOSE_EXIT:
return makeOpenCloseAnimation(mActivity, 1.0f, 1.075f, 1, 0);
case ANIM_STYLE_FADE_ENTER:
return makeFadeAnimation(mActivity, 0, 1);
case ANIM_STYLE_FADE_EXIT:
return makeFadeAnimation(mActivity, 1, 0);
}
根据之前这些逻辑,代码运行到这里,就应该算是结束了。但该方法,后面还有一些代码:
if (transitionStyle == 0 && mActivity.getWindow() != null) {
transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
}
if (transitionStyle == 0) {
return null;
}
对比了一样原始包中的FragmentManager,后面这段代码在那边还是有些差异的:
int styleIndex = transitToStyleIndex(transit, enter);
if (styleIndex < 0) {
return null;
}
if (transitionStyle == 0 && mActivity.getWindow() != null) {
transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
}
if (transitionStyle == 0) {
return null;
}
TypedArray attrs = mActivity.obtainStyledAttributes(transitionStyle,
com.android.internal.R.styleable.FragmentAnimation);
int anim = attrs.getResourceId(styleIndex, 0);
attrs.recycle();
if (anim == 0) {
return null;
}
return AnimatorInflater.loadAnimator(mActivity, anim);
所以,transitionStyle这个参数,在V4包这里是没有意义的。
好了,Fragment这个动画加载的方法内容就这些了。