編輯:關於Android編程
android動畫中的常用的三種動畫,即逐幀動畫(FrameAnimation),補間動畫(TweenAnimation)和屬性動畫(PropertyAniation).
首先就最簡單的FramAnimation入手,看看如何分別用代碼和xml文件實現。
如果是將動畫定義在xml文件中,無論是哪一種動畫,只要定義在xml文件中,我們都需要去在res目錄下創建一個anima的folder用於存儲和讀取定義的xml文件。
FrameAnimation的資源類型為drawable,標簽類型為animation-list(ps:套圖自己找,名字自己取)
oneshot的值有兩個true/false,表示動畫是否重復。
至此xml中的部分就完成了,只需要在代碼中初始化某一控件後(多為ImageView)添加設置動畫就可以了
image = (ImageView) findViewById(R.id.frame_image); image.setBackgroundResource(R.anim.frame); AnimationDrawable anim = (AnimationDrawable) image.getBackground(); anim.start();以上是設置ImageView的背景,當然也可以直接設置成圖片資源,效果都是一樣的。
image.setImageResource(R.drawable.animation2); animationDrawable = (AnimationDrawable) animationIV.getDrawable(); animationDrawable.start();
此時結束,動畫還是沒能顯示,出現這種現象是因為當我們在onCreate中調用AnimationDrawable的start方法時,窗口Window對象
還沒有完全初始化,AnimationDrawable不能完全追加到窗口Window對象中,那麼該怎麼辦呢?我們需要把這段代碼放在
onWindowFocusChanged方法中,當Activity展示給用戶時,onWindowFocusChanged方法就會被調用,我們正是在這個時候實現
我們的動畫效果。當然,onWindowFocusChanged是在onCreate之後被調用的。當然如果是將代碼寫入一個點擊監聽或者觸摸監聽
內,就沒這麼多事了。
接下來看一看如何用代碼進行逐幀動畫的實現,其實也很簡單
AnimationDrawable ad = new AnimationDrawable(); for (int i = 1; i <= 4; i++) { int resourcesId = getResources().getIdentifier(imageName(圖片的名字), "drawable", getPackageName()); Drawable drawable = getResources().getDrawable(resourceId); anim.addFrame(drawable, 300); } anim.setOneShot(false); image.setBackgroundDrawable(anim); 或者:image.setImageResource(anim); anim.start();
接下來我們來看一看補間動畫(TweenAnimation).
補間動畫又叫做View Animation,正如其名一樣,它只能對View和繼承View的控件視圖進行操作,而且操作也是視圖上的,是一系
列View形狀的變換,如大小的縮放,透明度的改變,位置的改變,真實的屬性是不會發生改變的,各個動畫效果之間可以連用,但
不會有影響,關於這一點,講到屬性動畫是會進行對比的。
首先我們來看一下,如何使用xml文件進行補間動畫的設置。
資源標簽為
AlphaAnimation:透明度(alpha)漸變效果,對應標簽。
TranslateAnimation:位移漸變,需要指定移動點的開始和結束坐標,對應標簽。
ScaleAnimation:縮放漸變,可以指定縮放的參考點,對應
RotateAnimation:旋轉漸變,可以指定旋轉的參考點,對應
AnimationSet:組合漸變,支持組合多種漸變效果,對應
可以通過startOffset屬性設置 各個動畫的開始偏移(開始時間)來達到動畫順序播放的效果。
可以通過設置interpolator屬性改變動畫漸變的方式,
如AccelerateInterpolator,開始時慢,然後逐漸加快。默認為AccelerateDecelerateInterpolator。
我從別人的博客截取了一張表,大家自己看:
博客地址:http://blog.csdn.net/qq_34381084/article/details/52228017
Interpolator的介紹
AccelerateDecelerateInterpolator 在動畫開始與介紹的地方速率改變比較慢,在中間的時候加速 AccelerateInterpolator 在動畫開始的地方速率改變比較慢,然後開始加速 CycleInterpolator 動畫循環播放特定的次數,速率改變沿著正弦曲線 DecelerateInterpolator 在動畫開始的地方速率改變比較慢,然後開始減速 LinearInterpolator 在動畫的以均勻的速率改變
這裡為了方便起見就一個set標簽搞定了,不多說,上代碼:
代碼控件設置就ok了。
Animation a=AnimationUtil.loadAnimation(R.drawable.name);
image.startAnimation(a);
接下來是代碼單純代碼設置動畫,簡單粗暴。
AnimationSet set = new AnimationSet(true); AlphaAnimation alphaAnimation=new AlphaAnimation(fromAlpha, toAlpha); set.addAnimation(alpha); animationSet.setFillBefore(true); animationSet.setFillAfter(false); animationSet.setDuration(200); ImageView.startAnimation(animationSet);
好了,最後是相對用的比較多的PropertyAnimation了。屬性動畫是android3.0以後推出的動畫類型,他的出現彌補了補間動畫的不
足之處,屬性動畫對於控件屬性的設置更改是真實的修改,而不僅僅是對於View的繪制,如果順序播放幾個動畫效果,是會互相影
響的。屬性動畫的作用對象不僅僅局限於View和其子類控件,就說一點,他的作用對象是object你就知道他的作用范圍有多廣了。
好的,菜鳥集中營,我們從頭說起:
屬性動畫中最核心的一個類ValuAnimator
ValueAnimator:
屬性動畫的運行機制是通過不斷地對值進行操作來實現的,
而初始值和結束值之間的動畫過渡就是由ValueAnimator這個類來負責計算的.
只需要將初始值和結束值提供給ValueAnimator,並且告訴它動畫所需運行的時長,
那麼ValueAnimator就會自動完成從初始值平滑地過渡到結束值這樣的效果。
ValueAnimator還負責管理動畫的播放次數、播放模式、以及對動畫設置監聽器等,確實是一個非常重要的類。
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); anim.setDuration(300); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); Log.d("TAG", "cuurent value is " + currentValue); } }); anim.start();通過log你可以清楚的看到animation值的變化過程。
ofFloat()方法當中允許傳入多個float類型的參數,這裡傳入0和1就表示將值從0平滑過渡到1,
然後調用ValueAnimator的setDuration()方法來設置動畫運行的時長,最後調用start()方法啟動動畫。
借助監聽器可以記錄屬性動畫的運行效果。
當然也許你並不需要小數位數的動畫過渡,可能你只是希望將一個整數值從0平滑地過渡到100,
那麼也很簡單,只需要調用ValueAnimator的ofInt()方法就可以了
ValueAnimator anim = ValueAnimator.ofInt(0, 100);
可以調用setStartDelay()方法來設置動畫延遲播放的時間
,
調用setRepeatCount()和setRepeatMode()方法來設置動畫循環播放的次數以及循環播放的模式,
循環模式包括RESTART和REVERSE兩種,分別表示重新播放和倒序播放的意思
ObjectAnimator:可以直接對任意對象的任意屬性進行動畫操作
ObjectAnimator會更加常用一些,但是它其實是繼承自ValueAnimator的,底層的動畫實現機制也是基於ValueAnimator來完成的
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f); animator.setDuration(5000); animator.start();將一個TextView在5秒中內從常規變換成全透明,再從全透明變換成常規
這裡第一個參數要求傳入一個object對象,想要對哪個對象進行動畫操作就傳入什麼,這裡傳入了一個textview。
第二個參數是想要對該對象的哪個屬性進行動畫操作,改變TextView的不透明度,因此這裡傳入"alpha"。
後面的參數就是不固定長度了,想要完成什麼樣的動畫就傳入什麼值,
這裡傳入的值就表示將TextView從常規變換成全透明,再從全透明變換成常規。
之後調用setDuration()方法來設置動畫的時長,然後調用start()方法啟動動畫
ObjectAnimator內部的工作機制並不是直接對我們傳入的屬性名進行操作的,而是會去尋找這個屬性名對應的get和set方法
組合動畫
實現組合動畫功能主要需要借助AnimatorSet這個類,這個類提供了一個play()方法,
如果我們向這個方法中傳入一個Animator對象(ValueAnimator或ObjectAnimator)將會返回一個AnimatorSet.Builder的實例,
AnimatorSet.Builder中包括以下四個方法:
after(Animator anim) 將現有動畫插入到傳入的動畫之後執行
after(long delay) 將現有動畫延遲指定毫秒後執行
before(Animator anim) 將現有動畫插入到傳入的動畫之前執行
with(Animator anim) 將現有動畫和傳入的動畫同時執行
Animator監聽器-----AnimatorListener();
監聽到動畫的各種事件,比如動畫何時開始,何時結束,然後在開始或者結束的時候去執行一些邏輯處理
Animator類當中提供了一個addListener()方法,這個方法接收一個AnimatorListener,
我們只需要去實現這個AnimatorListener就可以監聽動畫的各種事件了。
anim.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } });onAnimationStart()方法會在動畫開始的時候調用,
onAnimationRepeat()方法會在動畫重復執行的時候調用,
onAnimationEnd()方法會在動畫結束的時候調用,
onAnimationCancel()方法會在動畫被取消的時候調用。
Android提供了一個適配器類,叫作AnimatorListenerAdapter
anim.addListener(new AnimatorListenerAdapter() {
});
那麼如果我想監聽動畫結束這個事件,就只需要單獨重寫這一個方法就可以了
使用XML編寫動畫:通過XML來完成和代碼一樣的屬性動畫功能
通過XML來編寫動畫可能會比通過代碼來編寫動畫要慢一些,但是在重用方面將會變得非常輕松
然後在XML文件中的propertyAnimation資源標簽下,我們一共可以使用如下三種標簽:
對應代碼中的ValueAnimator
比如說我們想要實現一個從0到100平滑過渡的動畫,在XML當中就可以這樣寫:
而如果我們想將一個視圖的alpha屬性從1變成0,就可以這樣寫:
最後在代碼中添加設置控件代碼和補間動畫一樣,就不在重復了。
最後是幾個注意事項:
alpha動畫的從無到有是(0f,1f)
scale縮放分為X軸和Y軸,值的大小設置與alpha類似
rotate為翻轉,參數值為度數,所以如果設置的和alpha和scale相似就看不出什麼效果了
translation 為平移,分為X軸和Y軸,,參數為正向下移動,參數未負向上移動,代碼中參數的設置為px,同樣小了看不出效果
動畫是可以組合的,如果scale設置的參數為(1f,0f);那麼後面的動畫就看不出任何效果了,應為屬性在scale這裡就縮沒有了。
最後貼一段onClickListener,去掉中間的break,你會發現神奇的效果。
@Override public void onClick(View v) { switch(v.getId()){ case R.id.bt_alpha: ObjectAnimator al=ObjectAnimator.ofFloat(tv, "alpha", 0f,1f,0f,1f); al.setDuration(2000); al.start(); case R.id.bt_scaleX: ObjectAnimator sx=ObjectAnimator.ofFloat(tv, "scaleX", 0f,2f,4f,1f); sx.setDuration(2000); sx.start(); case R.id.bt_scaleY: ObjectAnimator sy=ObjectAnimator.ofFloat(tv, "scaleY", 0f,2f,4f,1f); sy.setDuration(2000); sy.start(); case R.id.bt_translationX: ObjectAnimator tx=ObjectAnimator.ofFloat(tv, "translationX", 0f,100f,-200f,0f); tx.setDuration(2000); tx.start(); case R.id.bt_translationY: ObjectAnimator ty=ObjectAnimator.ofFloat(tv, "translationY", 0f,100f,-200f,0f); ty.setDuration(2000); ty.start(); //沿著中心轉---tween中是左上角轉默認情況不一樣 case R.id.bt_rotation: ObjectAnimator ro=ObjectAnimator.ofFloat(tv, "rotation", 0f,360f,-360f,0f); ro.setDuration(2000); ro.start(); break; case R.id.bt_other: break; } }
Android由於其代碼是放在dalvik虛擬機上的托管代碼,所以能夠很容易的將其反編譯為我們可以識別的代碼。之前我寫過一篇文章反編譯Android的apk包到smali
最近在學習Android,隨著移動設備的流行,當軟件走上商業化的道路,為了爭奪市場,肯定需要支持Android的,所以開始接觸了Android,不過只了解皮毛就好,因為我
前面有關自定義View中進行了繪圖,但View的繪圖機制存在如下缺陷:1、View缺乏雙緩沖機制。2、當程序需要更新View上的圖像時,程序必須重繪View上顯示的整張圖
上一篇文章中我們講解了App的數據統計,其主要分為兩種:使用第三方服務統計和自身實現數據統計。一般而言我們使用第三方統計服務已經可以很好的滿足我們的也無需求了,只是部分數