編輯:關於Android編程
今天有時間來繼續寫寫屬性動畫。
眾所周知,屬性動畫是Android3.0版本開始的,一個東西的推出肯定是有它的道理的,那為什麼前面已經有逐幀和補間動畫了還要推出屬性動畫呢?
在前2篇的補間動畫中我們知道了我們可以對一個View進行:縮放、旋轉、平移、淡入淡出操作,並且可以做自定義補間動畫的操作。但是自定義補間動畫操作起來很麻煩,而自帶的那幾種使用起來雖然簡單,但是也僅限於這幾種了,補間動畫的機制其實就是使用硬編碼來完成的,功能已經限定死了,基本沒有任何擴展性可言。還有就是如果我們使用補間動畫使View往右移動一段距離,那麼其實這個View依然還在原點,並沒有真正移動,而使用屬性動畫移動到那個點就是在那個點。還有一個重要的點是,補間動畫只能夠作用在View上的,那麼如果你想對其他非View對象進行動畫操作,那就GG了。說了這麼多,相信大家已經知道補間和屬性動畫的區別了。
屬性動畫其對應的類是Animator,和補間動畫中的Animation一樣,Animator也是一個抽象類,其對應的繼承關系如下圖:
Animator有如下方法:
* addListener(Animator.AnimatorListener listener):監聽動畫的開始、重復、和結束。
* addPauseListener(Animator.AnimatorPauseListener listener):為動畫添加一個暫停監聽。
* cancel() :取消動畫
* clone():對動畫進行拷貝。
* end():結束動畫。
* getDuration():獲取動畫的持續時間。
* getInterpolator():獲取動畫的時間插補器。
* getListeners():獲取監聽器集合。
* getStartDelay():獲取動畫延遲開始的時間。
* isPaused():檢查動畫是否處於暫停狀態。
* isRunning():檢查動畫是否正在運行(已經啟動,並走過了startDelay(),尚未結束)
* isStarted():檢查動畫是否已經開始,沒有結束。
* pause():暫停正在運動的動畫。
* removeAllListeners():刪除所有的listeners 與pauseListeners對象。
* removeListener(Animator.AnimatorListener listener):移除指定的AnimatorListener監聽器。
* removePauseListener(Animator.AnimatorPauseListener listener):移除指定的AnimatorPauseListene監聽器。
* resume():恢復已經暫停的動畫。
* setDuration(long duration):設置動畫持續時間。
* setInterpolator(TimeInterpolator value):設置時間插值器。
* setStartDelay(long startDelay):設置動畫延遲多少毫秒後start()方法被調用。
* setTarget(Object target):設置目標對象。
* start():啟動動畫。
由於Animator是屬性動畫的基類,那麼其子類也都有上面的方法。我們在具體使用中我們通常會使用它的子類,下面具體來看看子類的使用。
首先來用ObjectAnimator實現下補間動畫中的操作。因為ObjectAnimator繼承自ValueAnimator,使用起來是最簡單的,分分鐘實現一個動畫:
* 新建一個布局文件:
代碼中實現點擊事件開啟了一個旋轉動畫:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void startAnim(View v){ ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(v, "rotation", 0.0f, 360f); rotateAnim.setDuration(3000); rotateAnim.start(); } }
運行結果:
可以看到,我們調用ofFloat(Object target, String propertyName, float… values) 構建ObjectAnimatZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcsqxuvKjrNa7tKvI68HL1eK49ravu63SqrLZ1/e1xFZpZXejrNLUvLCy2df31eK49lZpZXe1xMr00NSjrLu509C+zcrHv8mx5LLOo6y+zcq1z9bBy9K7uPa2r7utoaM8L3A+DQo8cD7Ex8O0zsrM4sC0wcujrLP9wcu0q8jrcm90YXRpb27K9NDU1q7N4qOsu7m/ydLUtKvI68m2yvTQ1MTYo788YnIgLz4NCsbkyrXU2s7Sw8fKudPDT2JqZWN0QW5pbWF0b3LX9ravu621xMqxuvKjrLKisrvKx7j5vt1YTUzW0Lao0uW1xMr00NTAtLjEseS1xKOstvjKx8ilzai5/da4tqi1xMr00NTIpbLp1dLL+bbU09q1xGdldKGic2V0t723qMC0uMSx5LXEoaPEx87Sw8fJz8PmtcSy2df3tcRJbWFnZVZpZXfT0HNldFJvdGF0aW9uKCm3vbeow7Sjv7TwsLjKx9PQtcSho7a8ysfNqLn9Vmlld7zMs9C2+MC0tcSho87Sw8e/ydLUv7S/tFZpZXfW0NK7ubLT0MTE0KnP4LnYtcS3vbeoo7o8L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;">
//1、透明度:alpha
public void setAlpha(float alpha)
//2、旋轉度數:rotation、rotationX、rotationY
public void setRotation(float rotation)
public void setRotationX(float rotationX)
public void setRotationY(float rotationY)
//3、平移:translationX、translationY
public void setTranslationX(float translationX)
public void setTranslationY(float translationY)
//縮放:scaleX、scaleY
public void setScaleX(float scaleX)
public void setScaleY(float scaleY)
知道了有哪些之後,我們可以繼續來驗證一下其他的動畫。
平移動畫:ObjectAnimator moveAnim = ObjectAnimator.ofFloat(v, "translationX", v.getTranslationX(), -200.0f, v.getTranslationX()); moveAnim.setDuration(3000); moveAnim.start();
運行結果:
* 透明動畫:
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(v, "alpha", 0.0f, 1.0f); alphaAnim.setDuration(3000); alphaAnim.start();
運行結果:
* 縮放動畫:
ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(v, "scaleX", 1.0f, 0.0f, 2.0f, 1.0f); scaleAnim .setDuration(3000); scaleAnim .start();
運行結果:
關於ObjectAnimator,我們只需知道一些簡單的用法就行了,真正的重頭戲在後面。
ValueAnimator直接繼承自抽象類Animator,它是整個屬性動畫中最核心的一個類了,其實上面寫到的ObjectAnimator就是對ValueAnimator的一個封裝實現。可以讓我們更方便的實現簡單的動畫效果。
屬性動畫的運行機制是通過不斷的對值進行操作來實現的,我們只需要把初始值和結束值給ValueAnimator,其內部會使用一種時間循環的機制來計算值與值之間的動畫過渡,來自動幫我們完成從初始值到結束值的平滑過度效果。
首先來看看ValueAnimator的用法,其實和ObjectAnimator類似,只不過少了屬性值的參數:
ValueAnimator animator = ValueAnimator.ofFloat(0f, 100f); animator.setDuration(300); animator.start();
可以看到,其實同構ObjectAnimator對比,ValueAnimator通過of…構建對象的參數只有一個可變參,而沒有了作用的View和屬性名。
這是因為,ValueAnimator只提供了平滑過度的值,而你要用這個值做什麼,完全由自己決定。
我們可以通過監聽來打印看看ValueAnimator提供給我們的值:
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); Log.i("test", "value: " + value); } });
打印結果:
07-30 10:05:56.128 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 0.0 07-30 10:05:56.145 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 0.7902175 07-30 10:05:56.163 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 3.1359017 07-30 10:05:56.179 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 7.231784 07-30 10:05:56.200 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 12.494448 07-30 10:05:56.220 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 18.942606 07-30 10:05:56.232 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 26.372465 07-30 10:05:56.249 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 35.047955 07-30 10:05:56.266 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 43.733345 07-30 10:05:56.283 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 52.616795 07-30 10:05:56.300 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 61.417534 07-30 10:05:56.318 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 70.33683 07-30 10:05:56.335 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 78.10417 07-30 10:05:56.352 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 84.98317 07-30 10:05:56.369 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 90.756386 07-30 10:05:56.387 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 95.46181 07-30 10:05:56.404 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 98.42916 07-30 10:05:56.421 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 99.86572 07-30 10:05:56.438 25367-25367/com.airsaid.propertyanimationdemo I/test: value: 100.0
通過ValueAnimator實現位移動畫:
ValueAnimator animator = ValueAnimator.ofFloat(0f, 100f, -100f, 0f); animator.setDuration(1000); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); v.setTranslationY(value); } }); animator.start();
運行結果:
AnimatorSet用於實現組合動畫,這個類提供了一個play()方法,如果我們向這個方法中傳入一個Animator對象(ValueAnimator或ObjectAnimator)將會返回一個AnimatorSet.Builder的實例,AnimatorSet.Builder中包括以下四個方法:
after(Animator anim) 將傳入的動畫在原有動畫執行之前執行:// 將after中傳入的縮放動畫在原有動畫之前執行 ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(v, "rotation", 0.0f, 360f); ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(v, "scaleX", 1.0f, 0.0f, 2.0f, 1.0f); AnimatorSet animSet = new AnimatorSet(); animSet.play(rotateAnim).after(scaleAnim); animSet.setDuration(1000); animSet.start();
運行結果:
animSet.play(rotateAnim).after(1000);
運行結果:
* before(Animator anim) 將插入的動畫在原有動畫執行之後執行:
animSet.play(rotateAnim).before(scaleAnim);
運行結果:
* with(Animator anim) 將插入的動畫和原有動畫同時執行:
animSet.play(rotateAnim).with(scaleAnim);
運行結果:
除了上面使用AnimatorSet實現了一組動畫播放之外,我們還可以通過PropertyValuesHolder實現一組動畫播放:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f); PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f); ObjectAnimator.ofPropertyValuesHolder(v, pvhX, pvhY,pvhZ).setDuration(1000).start();
運行結果:
Animator提供了一個動畫監聽的方法:addListener(),通過傳入一個AnimatorListener來實現監聽:
rotateAnim.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) { } });
如果你只想監聽動畫的結束,而又覺得每次都得實現所有的接口很繁瑣,那麼你可以試試Andorid給我們提供的適配器類:AnimatorListenerAdapter
rotateAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); } });
需要監聽哪個事件,只需單獨重寫一下該方法就行了。
除了在代碼中使用外,我們還可以在XML文件中定義屬性動畫。其中定義屬性動畫的XML資源文件能以如下三個元素中任意一個作為根元素:
*
XML中定義ObjectAnimator
代碼中使用:
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.anim_property);
animator.setTarget(v);
animator.start();
運行結果:
XML中定義ValueAnimator
代碼中使用:
ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.anim_property);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
Log.i("test", "value: " + value);
}
});
animator.start();
運行結果:
XML中定義AnimatorSet
代碼:
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.anim_property);
animator.setDuration(300);
animator.setTarget(v);
animator.start();
運行結果:
總結
合適的運用動畫會使我們的應用更有逼格。
大家好,趁著現在別人都去吃飯的時間,來給大家講一講React Native中Android部分的控件ViewPagerAndroid的講解,這裡特別提醒一下,我寫的博客都
board_init_r 函數中,兩個重要的過程就是 norflash 的識別和 nandflash 的識別,norflash 的識別過程以及如何移植前邊已經分析過,本文
1.本文將向你介紹自定義進度條的寫法,比較簡單,但還是有些知識點是需要注意的:invalidate()方法RectF方法的應用onMeasure方法的應用2.原理畫3層圓
小米Note全網通版是一款支持電信、聯通、移動手機卡的雙卡雙待手機,是小米Note標准版的升級版,但售價僅比標准版多了100元。下面下載吧小編就為大家總結小