異常
Caused by: java.lang.RuntimeException: Unknown animation name: objectAnimator
異常代碼
FragmentTransaction ft = getFragmentManager().beginTransaction(); //setCustomAnimations()必須位於replace()之前,否則效果不起所中。它的兩個參數分別為enter,exit的效果。系統目前提供兩個效果,分別為android.R.animator.fade_in和android.R.animator.fade_out ft.setCustomAnimations(R.animator.slide_in_left,R.animator.slide_out_right); ft.addToBackStack(null); ft.replace(R.id.details,"detail"); ft.commit();
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:interpolator/accelerate_decelerate" android:valueFrom="-1280" android:valueTo="0" android:valueType="floatType" android:propertyName="X" android:duration="2000" />
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:interpolator/accelerate_decelerate" android:valueFrom="0" android:valueTo="1280" android:valueType="floatType" android:propertyName="X" android:duration="2000" />
動畫簡單說明
實現自定義動畫的類是ObjectAnimator,不僅用於fragment,也可用於view。在xml中,定義了從“from”狀態到“to”狀態,時間間隔為duration(毫秒),所執行的變化規則稱為interpolator。最簡單的interpolator是linear,即@android:interpolator/linear,從狀態From到to狀態是均勻變化。缺省的interpolator是accelerate_decelerate。系統提供的方式可以在源代碼/data/res/interpolator中查看。android:propertyName用於動畫的維度,在本例中X表示橫向,根view的setX()中的參數是float,所以設置valueType為floatType。我們設置可以設置自己的維度。From設置為-1280,因為這個值對於終端設備而言,-1280個像素位可以確保從不可視的位置移入。如果我們沒有設置From,系統會根據當前值來設定初始值。
如果我們要在兩個或者兩個以上的維度設置變化,可以使用set tag,對應為Android的AnimatorSet類,下面的例子同時設置向下和淡出效果。set有一個屬性android:ordering,缺省為together,即各個維度的變化同時發生,還可以設置為sequentially依次發生。
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <objectAnimator android:interpolator="@android:interpolator/accelerate_cubic" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:propertyName="alpha" android:duration="1000"/> <objectAnimator android:interpolator="@android:interpolator/accelerate_cubic" android:valueFrom="0" android:valueTo="1280" android:valueType="floatType" android:propertyName="Y" android:duration="1000"/> </set>
異常分析
V4包中的Fragment對於動畫的支持不完全。
在FragmentManager類中的loadAnimation方法
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); return null;
在AnimatorInflater.loadAnimator里面處理的動畫:
String name = parser.getName(); if (name.equals("objectAnimator")) { anim = loadObjectAnimator(c, attrs); } else if (name.equals("animator")) { anim = loadAnimator(c, attrs, null); } else if (name.equals("set")) { anim = new AnimatorSet(); TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AnimatorSet); int ordering = a.getInt(com.android.internal.R.styleable.AnimatorSet_ordering, TOGETHER); createAnimatorFromXml(c, parser, attrs, (AnimatorSet) anim, ordering); a.recycle(); } else { throw new RuntimeException("Unknown animator name: " + parser.getName()); }
private static ObjectAnimator loadObjectAnimator(Context context, AttributeSet attrs) throws NotFoundException { ObjectAnimator anim = new ObjectAnimator(); loadAnimator(context, attrs, anim); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.PropertyAnimator); String propertyName = a.getString(com.android.internal.R.styleable.PropertyAnimator_propertyName); anim.setPropertyName(propertyName); a.recycle(); return anim; }
So
在使用V4包中Fragment時,使用的切換動畫效果,其動畫文件中不能包含objectAnimator,Animator這類標簽。如果必須要使用,請將工程中使用的V4包中Fragment相關類,換成源碼中的Fragment相關類。