Android 動畫
Android中動畫分為三種:
-
逐幀動畫
-
補間動畫
-
屬性動畫
逐幀動畫
逐幀動畫類似于gif或是電影的原理,通過將一系列圖片連續播放來獲得動畫效果。它本質是一種Drawable,由ImageView播放。
定義逐幀動畫有兩種方式:
drawable文件夾下定義xml:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="boolean">
<item
android:drawable="@..."
android:duration="integer"/>
<item .../>
</animation-list>
android:oneshot 指示是否重復播放
java代碼:
創建 AnimationDrawable 對象,使用 addFrame(Drawable frame, int duration) 向動畫添加幀。
AnimationDrawable默認是不播放的,調用 start() 、 stop() 來控制動畫的播放和停止。
補間動畫
補間動畫指定動畫開始和結束時的狀態(透明度、大小、位移、旋轉等),由系統根據指定的Interpolator(插值器)來生成過程幀,并實現動畫過程。
補間動畫有個很明顯的缺點, 動畫改變的只是顯示,并沒有改變事件響應的位置 。比方說我們通過補間動畫將Button移到了另一個位置,但是我們依然得點Button原來的位置才能觸發Button的點擊事件。
動畫的顯示會依賴于父控件的大小,若父控件太小,動畫可能會移出父控件邊緣,導致動畫不可見。
創建動畫的基本流程:
-
創建動畫實例
-
設置動畫持續時間、插值器等
-
調用view的 startAnimation() 方法并傳入動畫實例
-
透明度動畫
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1); alphaAnimation.setDuration(1000); view.startAnimation(alphaAnimation)
0代表完全透明,1為不透明。
-
旋轉動畫
RotateAnimation rotateAnimation = new RotateAnimation(0, 720, 75, 75); // 開始角度、結束角度、旋轉中心X坐標、旋轉中心Y坐標(此處X,Y是以View自身為參考系) RotateAnimation rotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 2f, Animation.RELATIVE_TO_SELF, 2f);// 開始角度、結束角度、X旋轉參考,X方向上與自身大小比值、Y旋轉參考,Y方向上與自身大小比值(參考系依然為View本身)
旋轉動畫可指定旋轉中心的坐標與參考View寬高的比值, RELATIVE_TO_SELF 或 RELATIVE_TO_PARENT ,值得注意的是,X,Y的坐標始終是以 View自身為參考系 。
-
位移動畫
TranslateAnimation translateAnimation = new TranslateAnimation(0, 200, 0, 300);// 起始X、結束X、起始Y、結束Y TranslateAnimation translateAnimation = new TranslateAnimation( Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 2);// 相對方式
-
縮放動畫
ScaleAnimation scaleAnimation = new ScaleAnimation(0.5f, 2, 0.5f, 2);// 數字表倍率 ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);// 指定縮放中心坐標
-
動畫集合
通過AnimationSet,可以組合各種動畫,使其同時播放
AnimationSet animationSet = new AnimationSet(true); animationSet.addAnimation(alphaAnimation); animationSet.addAnimation(rotateAnimation); animationSet.addAnimation(translateAnimation); animationSet.addAnimation(scaleAnimation); animationSet.setInterpolator(new AccelerateInterpolator()); animationSet.setDuration(1000); image.startAnimation(animationSet);
-
監聽器
有時候我們需要監聽動畫的開始或結束等來做進一步操作,這時候可以對動畫設置監聽器:
animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } });
屬性動畫
屬性動畫,顧名思義,是對針對屬性的動畫,通過持續地改變某個屬性來實現View的動畫效果。與補間動畫不同,屬性動畫真實地改變了View的屬性值。
-
ObjectAnimator
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(button, "translationX", 300); objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); objectAnimator.setDuration(300); objectAnimator.start();
要操作的屬性必須具有get和set方法。如果屬性沒有get、set方法,可以自定義一個包裝類:
private static class WrapperView { private View mTarget; public WrapperView(View target) { this.mTarget = target; } public int getWidth() { return mTarget.getLayoutParams().width; } public void setWidth(int width) { mTarget.getLayoutParams().width = width; mTarget.requestLayout(); } }
-
PropertyValuesHolder
要同時針對多個屬性進行動畫時使用:
PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofFloat("translationX", 300); PropertyValuesHolder propertyValuesHolder2 = PropertyValuesHolder.ofFloat("scaleX", 1, 0.1f); PropertyValuesHolder propertyValuesHolder3 = PropertyValuesHolder.ofFloat("scaleY", 1, 0.1f); ObjectAnimator.ofPropertyValuesHolder(button, propertyValuesHolder1, propertyValuesHolder2, propertyValuesHolder3).setDuration(1000).start();
-
ValueAnimator
ValueAnimator更像是一個數值發生器,使用時通過監聽數值的變換來自己完成動畫的實現:
ValueAnimator animator = ValueAnimator.ofFloat(0, 100); animator.setTarget(view); animator.setDuration(1000).start(); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Float value = (Float) animation.getAnimatedValue(); // TODO use the value } });
-
動畫時間監聽
一個完整動畫有四個過程:start、repeat、end、cancel。有兩種監聽器可以選:
animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } });
或:
animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); } });
AnimatorListenerAdapter可以按需要實現監聽start、repeat、end、cancel、pause、resume過程。
-
AnimatorSet
AnimatorSet 不能能像PropertyValuesHolder那樣同時實現多個動畫,同時還能精準控制動畫的順序:
ObjectAnimator animator1 = ObjectAnimator.ofFloat(button, "translationX", 300); ObjectAnimator animator2 = ObjectAnimator.ofFloat(button, "scaleX", 1, 0, 1); ObjectAnimator animator3 = ObjectAnimator.ofFloat(button, "scaleY", 1, 0, 1); AnimatorSet set = new AnimatorSet(); set.setDuration(1000); set.playTogether(animator1, animator2, animator3); set.start();
playTogether、playSequentially、play().with()、play().before()、play().after()等來控制動畫順序。
-
xml中使用屬性動畫
animator文件夾下xml:
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="2.0" android:valueType="floatType"> </objectAnimator>
java代碼中:
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.scalex); animator.setTarget(view); animator.start();
-
view的animate方法
button.animate().alpha(0).y(300).setDuration(300) .withStartAction(new Runnable() { @Override public void run() { } }) .withEndAction(new Runnable() { @Override public void run() { } }) .start();
布局動畫
布局動畫是作用在ViewGroup上當布局中View增加的動畫過渡效果。可在xml中添加 android:animateLayoutChanges="true" ,為布局添加默認動畫。
java中自定義動畫:
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);
sa.setDuration(1000);
LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5f); // 第二個參數是延遲
lac.setOrder(LayoutAnimationController.ORDER_NORMAL); // 當延遲不為0時,可指定View顯示順序,還有隨機和反序
ll.setLayoutAnimation(lac);
來自:http://www.jianshu.com/p/e1591694ccbe