幀動畫android
⑴ Android幀動畫/AnimationDrawable導致的OOM/ANR的解決方案
如果有播放超多幀動畫的需求,直接點擊 FrameAnimation 在github查看,基本能滿足你的所有需求,就不用往下看了,基本能滿足 99.99% 人的需求。
當在應用中需要使用幀動畫的時候,最先想到的就是Android提供的AnimationDrawable了,但是如果幀動畫中如果包含上百幀圖片,此時再用AnimationDrawable就不是那麼理想了。AnimationDrawable使用一個Drawable數組來存儲每一幀的圖像,會直接把全部圖片載入進內存。隨著幀數量的增多,就算性能再強勁的機器也會卡頓、OOM。
最近的項目中需要用到大量的幀動畫(各種閃瞎24K鈦合金狗眼的禮物效果,多的高達200幀),既然AnimationDrawable不行,就想到了兩種解決方法。
因為是直播的項目,包含人臉貼圖等都是用opengl繪制的,如果用OpenGL繪制一層Texture直接推流還省事。只在主播端處理就行了,但是IOS那邊都弄得差不多了,直接原生的不用處理也不會有什麼異常什麼的。。很尷尬。
好吧,第一個不行那就想到Android自帶的surfaceView啦。我首先用不同的手機測試了下應用從本地decode一個bitmap的時間(png格式,414*736,大小在30-100k之間),因為幀動畫的每幀不會太大,在性能好點的設備上基本保持在10-30ms之間(不推流基本上推流狀態下10ms左右,推流狀態下20左右),在性能稍差的設備中基本上也不會超過50ms,所以說是沒什麼大問題的。
既然不能完全載入到內存,想到的就是類似視頻播放或者視頻直播類似的思路。首先定義一個Bitmap的緩沖區,邊繪制邊載入。首先載入一定數量的幀到Bitmap緩沖區,載入完成後通知SurfaceView開始繪制。SurfaceView繪制一幀完成後通知Bitmap緩沖區載入下一幀,同時將繪制過的一幀的從Bitmap緩沖區移除。一幀繪制完成後,繪制線程根據設置的幀間隔休眠一段時間,休眠完成後開始從Bitmap緩沖區獲取下一幀,依此類推,一直循環,直到播放完成或者手動停止。按照這種方式實現起來,發現oom卡頓什麼的果然不存在了,內存的使用情況如圖。
但是看著這個垃圾桶一個挨一個,這個內存回收情況完全不正常!GC太頻繁了。想著應該是這里出現了問題。[圖片上傳失敗...(image-96f387-1512626035688)]
頻繁的添加移除bitmap,導致了不算太嚴重的內存抖動。之所以稱之為不算太嚴重,因為大概400ms一次,一次gc花費2ms左右。不看內存,只看運行效果。真的感覺不出來。但是呢,這樣顯然也是不行滴。
最常見的解決方法就是對象的復用,創建各種pool。Android也提供了Bitmap的復用方式,在載入bitmap的時候傳入一個inBitmap,那麼載入的bitmap就會復用原bitmap的內存空間,所以理論上將要復用的bitmap和新載入的bitmap在顏色深度一樣的情況下,復用的bitmap寬高要大於新載入的bitmap。50L的桶畢竟最多隻能裝50L的水。關於inBitmap更多資料可以參考 這里 , 還有這里 。(請自備梯子)。 使用起來很簡單,大概就是這樣
然後實現思路就是在這里修改了,把將要刪除的哪一幀留下來作為inBitmap。
⑵ 用 ConstraintLayout 和 ConstraintSet 實現 Android 關鍵幀動畫
關鍵幀動畫是一種動畫技術,它通過指定動畫開始和結束狀態,讓系統自動計算並實現動畫過程中的過渡狀態。在 Android 開發中,利用 ConstraintLayout 和 ConstraintSet 可以輕松實現關鍵幀動畫。
首先,在初始布局中,將要動畫展示的組件(如 TextView)放置於屏幕之外,確保動畫組件能夠覆蓋整個屏幕。初始布局中可以設定組件的全部屬性,如字體大小、顏色等。
對於最終狀態的布局,則只需定義各組件的最終位置。在實際開發中,開發者通常會提前設計並准備好這些布局文件。
接著,利用 TransitionManager 來計算並創建從初始布局到最終布局的動畫路徑。TransitionManager 默認提供勻速動畫,若需自定義動畫效果,開發者可以創建自定義的 transition,以實現所需動畫。
通過上述步驟,只需寥寥四行代碼,即可完成關鍵幀動畫的實現。這不僅簡化了動畫開發流程,也使得動畫效果更加豐富多樣。
欲了解更多關於關鍵幀動畫的實現細節,推薦觀看 YouTube 視頻:Keyframe Animations with ConstraintLayout and ConstraintSet。
⑶ android中的動畫有哪幾類,它們的特點和區別是什麼
在Android中,動畫技術的運用為用戶界面增添了生動性和交互性。動畫可以分為兩種主要類型:補間動畫和幀動畫。
補間動畫通過指定一個View的初始狀態和目標狀態,以及動畫變化的時間和方式,來實現圖形內容的動態變化。這種動畫效果主要包含四種:Alpha動畫調整透明度,Scale動畫改變大小,Translate動畫實現位置移動,Rotate動畫進行旋轉。
相比之下,幀動畫採用預先定義的一系列圖像幀,每幀對應動畫的一個特定時間點,通過連續播放這些圖像幀來構成動畫效果。每幀之間的切換時間由開發者設定,以此來控制動畫的流暢度和速度。
補間動畫和幀動畫在實現動畫效果時各有優勢。補間動畫通過動態計算實現平滑過渡,適用於需要自然流暢變化的動畫場景;而幀動畫通過直接播放預定義的圖像序列,適用於需要精確控制每一幀內容和播放速度的動畫設計。
理解這兩種動畫類型的特點與區別對於在Android應用開發中高效利用動畫技術至關重要。補間動畫適合實現自然流暢的動畫效果,而幀動畫則適用於需要精確控制每一幀的動畫場景。根據具體需求和場景選擇合適的動畫類型,可以有效提升用戶界面的交互性和視覺體驗。
⑷ android中的動畫有哪幾類,它們的特點和區別是什麼
Android中的常用動畫有三種:
1、View Animation(Tween Animation 補間動畫)
動畫的對象除了傳統的View對象,還可以是Object對象,動畫之後,Object對象的屬性值被實實在在的改變了。Propertyanimation能夠通過改變View對象的實際屬性來實現View動畫。任何時候View屬性的改變,View能自動調用invalidate()來試試刷新。
⑸ android中的動畫有哪幾類
在Android3.0(即API Level11)以前,Android僅支持2種動畫:分別是Frame Animation(逐幀動畫)和Tween Animation(補間動畫),在3.0之後Android支持了一種新的動畫系統,稱為:Property Animation(屬性動畫)。
一、Frame Animation:(逐幀動畫)
這個很好理解,一幀幀的播放圖片,利用人眼視覺殘留原理,給我們帶來動畫的感覺。它的原理的GIF圖片、電影播放原理一樣。
1.定義逐幀動畫比較簡單,只要在中使用子元素定義所有播放幀即可。
(1) android:oneshot 設置是否僅播放一次
(2) android:drawable 設置每一幀圖片
(3) android:ration 設置圖片間切換間隔
2.習慣上把AnimationDrawable設置為ImageView的背景
android:background=@anim/frame_anim
然後我們就可以在java代碼中獲取AnimationDrawable對象了
AnimationDrawable anim = (AnimationDrawable)imageView.getBackground();
(需要注意的是,AnimationDrawable默認是不播放的,調用其start()方法開始播放,stop停止播放)
3.上面的動畫文件是通過xml文件來配置的,如果你喜歡,也可以通過在java代碼中創建AnimationDrawable對象,然後通過addFrame(Drawable frame, int ration)方法向動畫添加幀,然後start()。。。
二、Tween Animation:(補間動畫)
補間動畫就是我們只需指定開始、結束的「關鍵幀「,而變化中的其他幀由系統來計算,不必自己一幀幀的去定義。
1. Android使用Animation代表抽象動畫,包括四種子類:AlphaAnimation(透明度動畫)、ScaleAnimation(縮放動畫)、TranslateAnimation(位移動畫)、RotateAnimation(透明度動畫)。Android裡面允許在java中創建Animation類對象,但是一般都會採用動畫資源文件來定義動畫,把界面與邏輯分離
<set android:interpolator="@android:anim/linear_interpolator" xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定義透明度的變換 -->
<!-- 定義旋轉變換 -->
<rotate android:ration="3000/" android:fromdegrees="0" android:pivotx="50%" android:pivoty="50%" android:todegrees="1800">
</rotate></alpha></set>
(一個set可以同時定義多個動畫,一起執行。)
2. android:interpolator=@android:anim/linear_interpolator控制動畫期間需要補入多少幀,簡單來說就是控制動畫速度,有些地方翻譯為「插值「。Interpolator有幾種實現類:LinearInterpolator、AccelerateInterpolator、、CycleInterpolator、DecelerateInterpolator,具體使用可以參考官方API Demo。
3. 定義好anim文件後,我們可以通過AnimationUtils工具類來載入它們,載入成功後返回一個Animation。然後就可以通過View的startAnimation(anim)開始執行動畫了。
Animation anim = AnimationUtils.loadAnimation(this, R.anim.anim);
//設置動畫結束後保留結束狀態
anim.setFillAfter(true);
//設置插值效果
anim.setInterpolator(interpolator);
//對view執行動畫
view. startAnimation(anim);
三、Property Animation:(屬性動畫)
屬性動畫,這個是在Android 3.0中才引進的,它可以直接更改我們對象的屬性。在上面提到的Tween Animation中,只是更改View的繪畫效果而View的真實屬性是不改變的。假設你用Tween動畫將一個Button從左邊移到右邊,無論你怎麼點擊移動後的Button,他都沒有反應。而當你點擊移動前Button的位置時才有反應,因為Button的位置屬性木有改變。而Property Animation則可以直接改變View對象的屬性值,這樣可以讓我們少做一些處理工作,提高效率與代碼的可讀性。
(1)ValueAnimator:包含Property Animation動畫的所有核心功能,如動畫時間,開始、結束屬性值,相應時間屬性值計算方法等。應用ValueAnimator有兩個步驟
1計算屬性值。
2根據屬性值執行相應的動作,如改變對象的某一屬性。
我們的主是第二步,需要實現ValueAnimator.onUpdateListener介面,這個介面只有一個函數onAnimationUpdate(),將要改變View對象屬性的事情在該介面中do。
animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//do your work
}
});
(2)ObjectAnimator:繼承自ValueAnimator,要指定一個對象及該對象的一個屬性,當屬性值計算完成時自動設置為該對象的相應屬性,即完成了Property Animation的全部兩步操作。實際應用中一般都會用ObjectAnimator來改變某一對象的某一屬性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,應該滿足以下條件:
1.對象應該有一個setter函數:set(駝峰命名法)
2如下面的例子,像ofFloat之類的工場方法,第一個參數為對象名,第二個為屬性名,後面的參數為可變參數,如果values…參數只設置了一個值的話,那麼會假定為目的值,屬性值的變化范圍為當前值到目的值,為了獲得當前值,該對象要有相應屬性的getter方法:get
3如果有getter方法,其應返回值類型應與相應的setter方法的參數類型一致。
ObjectAnimator oa=ObjectAnimator.ofFloat(tv, alpha, 0f, 1f);
oa.setDuration(3000);
oa.start();
如果不滿足上面的條件,我們只能乖乖的使用ValueAnimator來創建動畫。
(3)Animator.AnimatorListener:可以為Animator設置動畫監聽,需要重寫下面四個方法。
onAnimationStart()
onAnimationEnd()
onAnimationRepeat()
onAnimationCancel()
這里我們也可以實現AnimatorListenerAdapter,他的好處是可以只用定義想監聽的事件而不用實現每個函數卻只定義一空函數體。如下:
anim.addListener(new AnimatorListenerAdapter() {
public void on AnimationEnd(Animator animation){
//do your work
}
});
(4)AnimationSet:可以組合多個動畫共同工作
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(anim1).before(anim2);
bouncer.play(anim2).with(anim3);
bouncer.play(anim2).with(anim4)
bouncer.play(anim5).after(amin2);
animatorSet.start();
上面的代碼意思是: 首先播放anim1;同時播放anim2,anim3,anim4;最後播放anim5。
(5)TimeInterplator:與Tween中的interpolator類似。有以下幾種
AccelerateInterpolator 加速,開始時慢中間加速
DecelerateInterpolator 減速,開始時快然後減速
先加速後減速,開始結束時慢,中間加速
AnticipateInterpolator 反向 ,先向相反方向改變一段再加速播放
反向加回彈,先向相反方向改變,再加速播放,會超出目的值然後緩慢移動至目的值
BounceInterpolator 跳躍,快到目的值時值會跳躍,如目的值100,後面的值可能依次為85,77,70,80,90,100
CycleIinterpolator 循環,動畫循環一定次數,值的改變為一正弦函數:Math.sin(2 * mCycles * Math.PI * input)
LinearInterpolator 線性,線性均勻改變
OvershottInterpolator 回彈,最後超出目的值然後緩慢改變到目的值
TimeInterpolator 一個介面,允許你自定義interpolator,以上幾個都是實現了這個介面
(6)Keyframes:可以讓我們定義除了開始和結束以外的關鍵幀。KeyFrame是抽象類,要通過ofInt(),ofFloat(),ofObject()獲得適當的KeyFrame,然後通過PropertyValuesHolder.ofKeyframe獲得PropertyValuesHolder對象,如下:
Keyframe kf0 = Keyframe.ofInt(0, 400);
Keyframe kf1 = Keyframe.ofInt(0.25f, 200);
Keyframe kf2 = Keyframe.ofInt(0.5f, 400);
Keyframe kf4 = Keyframe.ofInt(0.75f, 100);
Keyframe kf3 = Keyframe.ofInt(1f, 500);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe(width, kf0, kf1, kf2, kf4, kf3);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn, pvhRotation);
上述代碼的意思是:設置btn對象的width屬性值使其:開始時 Width=400,動畫開始1/4時 Width=200,動畫開始1/2時 Width=400,動畫開始3/4時 Width=100,動畫結束時 Width=500。
(7)ViewPropertyAnimator:對一個View同時改變多種屬性,非常推薦用這種。該類對多屬性動畫進行了優化,會合並一些invalidate()來減少刷新視圖。而且使用起來非常簡便,但是要求API LEVEL 12,即Android 3.1以上。僅需要一行代碼即可完成水平、豎直移動
myView.animate().translationX(50f). translationY(100f);
(8)常需要改變的一些屬性:
translationX,translationY: View相對於原始位置的偏移量
rotation,rotationX,rotationY: 旋轉,rotation用於2D旋轉角度,3D中用到後兩個
scaleX,scaleY: 縮放比
x,y: View的最終坐標,是View的left,top位置加上translationX,translationY
alpha: 透明度
四、最後自己總結一下這三種動畫的優缺點:
(1)Frame Animation(幀動畫)主要用於播放一幀幀准備好的圖片,類似GIF圖片,優點是使用簡單方便、缺點是需要事先准備好每一幀圖片;
(2)Tween Animation(補間動畫)僅需定義開始與結束的關鍵幀,而變化的中間幀由系統補上,優點是不用准備每一幀,缺點是只改變了對象繪制,而沒有改變View本身屬性。因此如果改變了按鈕的位置,還是需要點擊原來按鈕所在位置才有效。
(3)Property Animation(屬性動畫)是3.0後推出的動畫,優點是使用簡單、降低實現的復雜度、直接更改對象的屬性、幾乎可適用於任何對象而僅非View類,缺點是需要3.0以上的API支持,限制較大!但是目前國外有個開源庫,可以提供低版本支持!
⑹ Android 中的動畫有哪幾類,它們的特點和區別是什麼
1.View Animation(Tween Animation):補間動畫,給出兩個關鍵幀,通過一些演算法將給定屬性值在給定的時間內在兩個關鍵幀間漸變。
View animation只能應用於View對象,而且只支持一部分屬性,這種實現方式可以使視圖組件移動、放大、縮小以及產生透明度的變化.
2.Frame動畫,傳統的動畫方法,通過順序的播放排列好的圖片來實現,類似電影補間動畫和幀動畫。
補間動畫和Frame動畫的定義:
所謂補間動畫,是指通過指定View的初末狀態和變化時間、方式,對View的內容完成一系列的圖形變換來實現動畫效果。主要包括四種效果:Alpha、Scale、Translate和Rotate。
幀動畫就是Frame動畫,即指定每一幀的內容和停留時間,然後播放動畫。。
3.屬性動畫
只是一個動畫效果,組件其實還在原來的位置上,xy沒有改變
###位移:
第一個參數target指定要顯示動畫的組件
第二個參數propertyName指定要改變組件的哪個屬性
第三個參數values是可變參數,就是賦予屬性的新的值
傳入0,代表x起始坐標:當前x + 0
傳入100,代表x終點坐標:當前x + 100
//具有get、set方法的成員變數就稱為屬性
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "translationX", 0, 100) ;
4.四種基本的動畫 ,透明/伸縮/移動/旋轉。
(1)XML中
alpha 漸變透明度動畫效果
scale 漸變尺寸伸縮動畫效果
translate畫面轉換位置移動動畫效果
rotate畫面轉移旋轉動畫效果
(2) JavaCode中
AlphaAnimation漸變透明度動畫效果
ScaleAnimation漸變尺寸伸縮動畫效果
TranslateAnimation畫面轉換位置移動動畫效果
RotateAnimation畫面轉移旋轉動畫效果
(3)Android動畫模式
Animation主要有兩種動畫模式:
一種是tweened animation(漸變動畫)
一種是frame by frame(畫面轉換動畫)
Tween動畫,這種實現方式可以使視圖組件移動、放大、縮小以及產生透明度的變化;
Frame動畫,傳統的動畫方法,通過順序的播放排列好的圖片來實現,類似電影。