標籤:repeat UI 之間 android動畫 注意 1.2 .com har 開發
Android動畫可以分為3類:View動畫,幀動畫,屬性動畫1.View動畫可以通過XML來建立,也可以通過代碼來建立1.1通過XML建立在res/anim下建立filename.xml檔案,文法如下所示
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@[package:]anim/interpolator_resource" android:shareInterpolator=["true" | "false"] > <alpha android:fromAlpha="float" android:toAlpha="float" /> <scale android:fromXScale="float" android:toXScale="float" android:fromYScale="float" android:toYScale="float" android:pivotX="float" android:pivotY="float" /> <translate android:fromXDelta="float" android:toXDelta="float" android:fromYDelta="float" android:toYDelta="float" /> <rotate android:fromDegrees="float" android:toDegrees="float" android:pivotX="float" android:pivotY="float" /> <set> ... </set></set>
View動畫不止能夠寫單個的動畫,也可以使用動畫集合.<set>代表動畫集合(對應於AnimationSet).1.1.1:interpolator:差值器,可以影響動畫的速度。1.1.2:shareInterpolator是否共用一個差值器,如果集合不指定差值器,子動畫就需要指定差值器或者使用預設的差值器。1.1.3:scale的軸點:pivotX和pivotY 軸點與在中間和在左右2側的效果是不同的。1.1.4:duration1.1.5:fillAfter動畫結束後是否停留在結束的位置。 具體例子
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="false" > <translate android:duration="100" android:fromXDelta="0" android:toXDelta="100" android:fromYDelta="0" android:toYDelta="100" android:interpolator="@android:anim/linear_interpolator"/> <rotate android:duration="400" android:fromDegrees="0" android:toDegrees="90" /></set>
使用方式
Animation animation = AnimationUtils.loadAnimation(AnimationActivity.this, R.anim.filename); mButton.startAnimation(animation);
1.2通過代碼建立略1.3View動畫使用情境A.ViewGroup子View的出場效果
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="300" android:interpolator="@android:anim/accelerate_interpolator" android:shareInterpolator="true"> <alpha android:fromAlpha="0.0" android:toAlpha="1.0"></alpha> <translate android:fromYDelta="500" android:toYDelta="0"></translate></set><?xml version="1.0" encoding="utf-8"?><layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="0.5" android:animationOrder="normal" android:animation="@anim/anim_item"></layoutAnimation> Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item); LayoutAnimationController controller = new LayoutAnimationController(animation); controller.setDelay(0.5f); controller.setOrder(LayoutAnimationController.ORDER_NORMAL); v.setLayoutAnimation(controller);//或者直接在XMl中使用 <ListView android:id="@+id/list" android:cacheColorHint="#00000000" android:divider="#dddbdb" android:dividerHeight="1.0px" android:background="#fff4f7f9" android:layoutAnimation="@anim/anim_layout" android:listSelector="@android:color/transparent" android:layout_width="match_parent" android:layout_height="wrap_content"></ListView>
delay是延時周期(如果周期是300ms延時就是0.5*300=150,第一個是150ms後開始動畫,第二個是延時300ms後開始變化,以此類推)B.Activity之間的轉場效果主要用到了overridePendingTransition這個方法,但是這個方法需要在startActivity之前和finish之後調用才會有效2.幀動畫3.屬性動畫
屬性動畫可以對任意對象的屬性進行動畫而不僅僅是View,在一定的時間間隔內完對象從一個屬性值到另一個屬性值得改變,但是屬性動畫是從Api11才開始有的.
常用的幾個類是:ValueAnimator.ObjectAnimator和AnimatorSet其中ObjectAnimator繼承自ValueAnimator,AnimatorSet是一個動畫集合.可以定義一組動畫。通過代碼實現單個屬性與屬性集合
private void startObjectAnimator(View object) { ObjectAnimator.ofFloat(object, "translationY", -object.getHeight()).start(); } private void startColorProperty(View view) { ValueAnimator colorAnim = ObjectAnimator.ofInt(view, "backgroundColor", 0xFFFF8080, 0xFF8080FF); colorAnim.setDuration(3000); colorAnim.setEvaluator(new ArgbEvaluator()); colorAnim.setRepeatCount(ValueAnimator.INFINITE); colorAnim.setRepeatMode(ValueAnimator.REVERSE); colorAnim.start(); } private void startSetProperty(View view) { AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(view, "rotationX", 0, 360), ObjectAnimator.ofFloat(view, "rotationY", 0, 360), ObjectAnimator.ofFloat(view, "rotation", 0, -90), ObjectAnimator.ofFloat(view, "translationX", 0, 90), ObjectAnimator.ofFloat(view, "translationY", 0, 90), ObjectAnimator.ofFloat(view, "scaleX", 1, 1.5f), ObjectAnimator.ofFloat(view, "scaleY", 0, 0.5f), ObjectAnimator.ofFloat(view, "alpha", 0, 0.25f, 1) ); set.setDuration(5 * 1000).start(); }
通過XML定義,屬性動畫定義在res/animator/下
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator android:propertyName="x" android:duration="300" android:valueTo="200" android:valueType="intType"></objectAnimator> <objectAnimator android:propertyName="y" android:duration="300" android:valueTo="300" android:valueType="intType"></objectAnimator> </set>
載入上面的動畫給View
AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.property_animator); animatorSet.setTarget(view); animatorSet.start();
理解差值器和估值器TimeInterpolator翻譯成時間差值器,他的作用是根據時間流逝的百分比來計算出當前屬性值改變的百分比.TypeEvaluator的中文翻譯是類型估值演算法,就是估值器,它的作用是根據當前屬性改變的百分比來計算改變後的屬性值.如果需要對其他類型做動畫(比如非int,float,color)這時候就需要自訂類型估值演算法.
屬性動畫注意事項:
屬性動畫要求對象的屬性有set和get(可選)方法.屬性動畫的監聽器屬性動畫對於監聽動畫的過程提供了兩個介面AnimatorUpdateListener和AnimatorListener
public static interface AnimatorListener { default void onAnimationStart(Animator animation, boolean isReverse) { onAnimationStart(animation); } default void onAnimationEnd(Animator animation, boolean isReverse) { onAnimationEnd(animation); } void onAnimationStart(Animator animation); void onAnimationEnd(Animator animation); void onAnimationCancel(Animator animation); void onAnimationRepeat(Animator animation); }
監聽了動畫的開始,結束,取消和重複,而且系統提供了AnimatorListenerAdapter這個類,方便我們去繼承上面幾個方法任意的組合.
public static interface AnimatorUpdateListener { void onAnimationUpdate(ValueAnimator animation); }
監聽動畫的整個過程,動畫是由許多幀來組成的,每播放一幀,onAnimatorUpdate就會調用一次.對任意屬性做動畫屬性動畫是根據外界傳遞給該屬性的初始值和最終值,通過不斷的調用set方法,每次傳遞給set方法的值都不一樣,但是越來越接近最終值.這樣,對object的abc屬性做動畫,需要動畫生效就需要滿足2個條件:(1):需要提供setAbc()方法,如果做動畫的時候沒有傳遞初始值,那麼還需要提供getAbc方法,因為系統要去取abc屬性的初始值(如果這條不滿足,程式直接 Crash).(2):object的setAbc()方法對屬性abc所做的改變必須通過某種方法反映出來,比如會帶來UI的改變之類的(如果這條不滿足,動畫無效但是不會Crash). 對於沒有提供get和set方法的屬性動畫,官方提供了3種解決辦法.對於屬性動畫的3種解決辦法:1.給你的對象加上get和set方法.2.採用一個類來封裝原始對象,間接為其提供get和set方法.3.採用ValueAnimator,監聽動畫過程,自己實現屬性的改變.1.給你的對象加上get和set方法這種通常對於SDK中的View,是沒有許可權的.2.用一個類來封裝原始對象,間接為其提供get和set方法.
private static class ViewWrapper { private View mTarget; public ViewWrapper(View target) { this.mTarget = target; } public void setWidth(int width) { mTarget.getLayoutParams().width = width; mTarget.requestLayout(); } public int getWidth() { return mTarget.getLayoutParams().width; } } //使用上面的封裝類 ViewWrapper wrapper = new ViewWrapper(view); ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();
本來想改變Button的width,結果setWidth改變的與我們想要的不是同一個東西,將Button包裹為target,通過改變其LayourParams的width來達到動畫的效果.3.採用ValueAnimator,監聽動畫過程,自己實現屬性的改變.ValueAnimator本身不作用於任何對象,也就是說直接使用它沒有任何效果,可以使用它對一個值做動畫,我們對一個值做動畫,然後監聽它的動畫過程,在過程中修改我們動畫的屬性值.
private void performAnimator(final View target, final int start, final int end) { ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { //估值對象,方便估值的時候使用 private IntEvaluator mEvaluator = new IntEvaluator(); @Override public void onAnimationUpdate(ValueAnimator animation) { //擷取當前的進度 int currentValue = (int) animation.getAnimatedValue(); float fraction = animation.getAnimatedFraction(); //重新計算width,然後設定給LayoutParams最後重新繪製 target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end); target.requestLayout(); } }); valueAnimator.setDuration(5000).start(); }
以上就是Android動畫的大概內容,其餘如屬性動畫的工作原理,沒有講述. 可能出現的問題:
1.View動畫是對View的影像做動畫,有時候會出現動畫完成了但是View無法隱藏的現象,就是setVisibility(View.GONE)失效了,這時候只要調用view.clearAnimation()清除View動畫就可以解決.2.在進行動畫的過程中,盡量使用dp,使用px會導致在不同的裝置上有不同的效果.
Android動畫(開發藝術探索讀書筆記)