[0 to 0.5]从零开始学习Android动画知识(上)
[0 to 0.5]從零開始學習Android動畫知識(上)
為什么要學習動畫
當然是因為COOL啊
用戶對產品的體驗是由多種要素構成的。
在APP開發過程中,影響產品最終形象的元素有很多,而動畫效果一直是其中不可或缺的一部分。
好的動畫效果不僅可以在單一界面中容納更多信息,傳達并反饋更多的狀態 (更炫酷);
還可以引導用戶對產品的交互,促進用戶對信息的理解,使用產品時更加流暢 (更簡單)。
動畫框架
Android的動畫本來有兩種:補間動畫(Tween Animation)和逐幀動畫(Frame Animation),并統稱為視圖動畫(View Animation),在Android3.0(API 11)之后又加入了屬性動畫 (Property Animation)。
#mermaid-svg-fGNwFpBC7U7hBc54 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-fGNwFpBC7U7hBc54 .error-icon{fill:#552222;}#mermaid-svg-fGNwFpBC7U7hBc54 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fGNwFpBC7U7hBc54 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-fGNwFpBC7U7hBc54 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fGNwFpBC7U7hBc54 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fGNwFpBC7U7hBc54 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fGNwFpBC7U7hBc54 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fGNwFpBC7U7hBc54 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fGNwFpBC7U7hBc54 .marker.cross{stroke:#333333;}#mermaid-svg-fGNwFpBC7U7hBc54 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fGNwFpBC7U7hBc54 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-fGNwFpBC7U7hBc54 .cluster-label text{fill:#333;}#mermaid-svg-fGNwFpBC7U7hBc54 .cluster-label span{color:#333;}#mermaid-svg-fGNwFpBC7U7hBc54 .label text,#mermaid-svg-fGNwFpBC7U7hBc54 span{fill:#333;color:#333;}#mermaid-svg-fGNwFpBC7U7hBc54 .node rect,#mermaid-svg-fGNwFpBC7U7hBc54 .node circle,#mermaid-svg-fGNwFpBC7U7hBc54 .node ellipse,#mermaid-svg-fGNwFpBC7U7hBc54 .node polygon,#mermaid-svg-fGNwFpBC7U7hBc54 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fGNwFpBC7U7hBc54 .node .label{text-align:center;}#mermaid-svg-fGNwFpBC7U7hBc54 .node.clickable{cursor:pointer;}#mermaid-svg-fGNwFpBC7U7hBc54 .arrowheadPath{fill:#333333;}#mermaid-svg-fGNwFpBC7U7hBc54 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fGNwFpBC7U7hBc54 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fGNwFpBC7U7hBc54 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-fGNwFpBC7U7hBc54 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-fGNwFpBC7U7hBc54 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fGNwFpBC7U7hBc54 .cluster text{fill:#333;}#mermaid-svg-fGNwFpBC7U7hBc54 .cluster span{color:#333;}#mermaid-svg-fGNwFpBC7U7hBc54 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fGNwFpBC7U7hBc54 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}AnimationView AnimationProperty AnimationFrame AnimationTween Animation視圖動畫(View Animation)
逐幀動畫(Frame Animation)
簡單來說,逐幀動畫就是將一組預先準備好的圖片通過控制依次顯示并循環播放(參考幻燈片),從而造成一種動畫效果。
通常逐幀動畫有兩種實現方式: XML 和 Java 。
用XML方法實現
首先,創建XML文件并加入每幀素材
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot= "false" > <item android:drawable="@drawable/type1" android:duration="150" /> <item android:drawable="@drawable/type2" android:duration="150" /></animation-list>- android:oneshot 代表是否循環(true 為不循環,false 為循環)
- drawable代表加入的圖片素材,而duration代表該素材一幀的持續時長(ms)
然后,將上述XML文件(frame.xml)作為ImageView(image)的圖像,并調用AnimationDrawable類獲取該圖像生成的實例
private ActivityMainBinding binding; private AnimationDrawable frame; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());binding.image.setImageResource(getResources().getIdentifier("frame","drawable",getPackageName()));frame = (AnimationDrawable) binding.image.getDrawable();//獲取實例binding.Start.setOnClickListener(view -> {frame.start();});binding.Stop.setOnClickListener(view -> {frame.stop();}); }效果如下:
[查看圖片]
用Java方法實現
Java代碼實現逐幀動畫和xml類似,相當于使用Java代碼獲取AnimationDrawable實例
private ActivityMainBinding binding; private AnimationDrawable frame; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());frame = new AnimationDrawable();for (int i = 1 ,id;i <= 2; i ++ ) {id = getResources().getIdentifier("type" + i, "drawable", getPackageName());frame.addFrame(getResources().getDrawable(id),150);}//相當于創建frame.xmlframe.setOneShot(false);//設置是否循環binding.image.setImageDrawable(frame);binding.Start.setOnClickListener(view -> {frame.start();});binding.Stop.setOnClickListener(view -> {frame.stop();}); }逐幀動畫的優缺點
優點:代碼量小,使用較為方便、簡單
缺點:動畫的變化基于圖片的切換,越是流暢的動畫越需要更多的圖片,從而占用了大量內存。所以,使用逐幀動畫時一定要注意圖片的大小和數目!
補間動畫(Tween Animation)
補間動畫是通過已確定的開始視圖樣式和結束視圖樣式,并由系統計算來補全其中間動畫變化過程的動畫
補間動畫同樣支持XML和Java兩種方法,這里我推薦使用更易讀、可切換、可重復使用的XML方法
Android支持的補間動畫效果有以下4種:旋轉(rotate)、位移(translate)、縮放(scale)和透明度(alpha)
| 縮放 | ScaleAnimation | <scale> | 進行特定范圍的縮放 |
| 透明度 | AlphaAnimation | <alpha> | 改變透明度,實現隱現 |
| 位移 | TranslateAnimation | <translate> | 進行位置的移動 |
| 旋轉 | RotateAnimation | <rotate> | 圍繞特定的點進行旋轉 |
| 復合 | AnimationSet | <set> | 復合使用上述四種效果 |
上述動畫的類均繼承自Animation類,因此存在一些通用的動畫屬性和方法
| android:duration | setDuration(long) | 動畫持續時間(ms) |
| android:fillAfter | setFillAfter(boolean) | 保持動畫結束時的狀態,默認ture |
| android:fillBefore | setFillBefore(boolean) | 還原到動畫開始時的狀態,默認為false |
| android:repeatCount | setRepeatCount(int) | 動畫重復執行的次數 |
| android:repeatMode | setRepeatMode(int) | 動畫重復模式 ,restart從頭開始,reverse倒敘回放 |
| android:startOffset | setStartOffset(long) | 動畫開始前延遲的時間(ms) |
| android:interpolator | setInterpolator(Interpolator) | 插值器,改變動畫的不同階段的執行速度 |
這里的插值器(interpolator)在屬性動畫中較為常用,我們將在后面細說。
透明度動畫(Alpha)
xml方法代碼
<?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android"android:duration="2000"android:fromAlpha="1.0"android:toAlpha="0.0"/> animation = AnimationUtils.loadAnimation(this,R.anim.alpha_anim);對應Java方法代碼
animation = new AlphaAnimation(1,0); animation.setDuration(4000); binding.tween.startAnimation(animation);這里的AlphaAnimation(float,float)的兩個值域為 [0,1] 的參數分別對應
XML中的android:fromAlpha(初始透明度) 和 android:toAlpha(終止透明度)
且值越接近0,透明度越高
效果如下:
[查看圖片]
旋轉動畫(Rotate)
xml方法代碼
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android"android:fromDegrees="0"android:toDegrees="180"android:pivotY="50%"android:pivotX="50%"android:duration="2000" />對應Java方法代碼
animation = new RotateAnimation(0,180,Animation.RELATIVE_TO_SELF,0.50f,Animation.RELATIVE_TO_SELF,0.50f); //RotateAnimation(fromDegrees,toDegrees,pivotXType,pivotX,pivotYType,pivotY) animation.setDuration(1000);顯然,RotataAnimation()的前兩個參數分別對應 android:fromDegrees(起始角度) 和 android:toDegrees(最終角度)
而這里多出來的兩個常數參數 pivotXType和pivotYType分別指定了如何去解釋pivotX和pivotY
| 指定尺寸是一個絕對像素數量。使用之后pivotX 或pivotY 的值都是絕對像素數量(px)。 | 指定尺寸是一個浮點數,用這個浮點數來乘動畫對象的寬或高。如使用之后動畫最終的x軸 =(pivotX 的值) * (動畫對象的寬),即百分數 | 指定尺寸是一個浮點數,用這個浮點數來乘動畫父對象的寬或高。如使用之后動畫最終的x軸 =(pivotX 的值) * (動畫父對象的寬),即百分數 |
效果如下:
[查看圖片]
縮放動畫(Scale)
xml方法代碼
<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1000"android:fromXScale="0.0"android:fromYScale="0.0"android:pivotX="50%"android:pivotY="50%"android:toXScale="1.0"android:toYScale="1.0" />對應Java方法代碼
animation = new ScaleAnimation(0,1,0,1,Animation.RELATIVE_TO_SELF,0.50f,Animation.RELATIVE_TO_SELF,0.50f); //ScaleAnimation(fromXScale,toXScale,fromYScale,toYScale,pivotXType,pivotX,pivotYType,pivotY) animation.setDuration(1000);這里的fromXScale和toXScale分別確定了開始和結尾的縮放比例,而pivotX確定了縮放的中心
效果如下:
[查看圖片]
位移動畫(Translate)
xml方法代碼
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1000"android:fromXDelta="0"android:fromYDelta="0"android:toXDelta="0%"android:toYDelta="130%" />對應Java方法代碼
animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,1,0,1,0,1,1.30f); //TranslateAnimation(fromXType,fromXDelta,toXType,toXDelta,fromYType,fromYDelta,toYType,toYDelta) //這里為了控制代碼長度,將Animation.RELATIVE_TO_SELF換成其對應值1 //還有一種常用的動畫 TranslateAnimation(fromXDelta,toXDelta,fromYDelta,toYDelta) //這時Delta代表的是坐標值 animation.setDuration(1000);位移動畫(Translate)的參數與旋轉動畫(Rotate)中的使用方法一致,不同的fromXType有不同的fromXDelta解釋與之對應。
但要注意,Translate的百分數位置起始點是其左上角,即當fromDelta為0時,圖像從左上角出發
效果如下:
[查看圖片]
復合動畫(Set)
顧名思義,Set動畫即前幾個動畫的復合使用
xml方法代碼
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"android:interpolator="@android:anim/linear_interpolator"android:shareInterpolator="true"android:duration="2000"><alphaandroid:fromAlpha="0.5"android:toAlpha="1.0"/><scaleandroid:fromXScale="0.0"android:fromYScale="0.0"android:pivotX="50%"android:pivotY="50%"android:toXScale="1.0"android:toYScale="1.0"/><translateandroid:fromXDelta="0"android:fromYDelta="0"android:toXDelta="0%"android:toYDelta="100%"/><rotateandroid:fromDegrees="0"android:toDegrees="360"android:pivotY="50%"android:pivotX="50%"android:repeatCount="100"/> </set>對應Java方法代碼
AnimationSet animationSet = new AnimationSet(true); //AnimationSet(shareInterpolator) animationSet.addAnimation(animation); //只需將之前的其他動畫的animation “加入” animationSet即可 binding.tween.startAnimation(animationSet);AnimationSet(shareInterpolator)中的shareInterpolator是一個boolean類型的值
其為true時代表所有子動畫共用一個Interpolator , linear_interpolator代表動畫變化均勻
效果如下:
[查看圖片]
Tween Animation的監聽
動畫監聽器可以對動畫的執行狀態進行監聽,并通過重寫進行一系列操作
Animation.addListener(new AnimatorListener() {@Overridepublic void onAnimationStart(Animation animation) {//監聽動畫開始//對應animation.start()}@Overridepublic void onAnimationRepeat(Animation animation) {//監聽動畫重復}@Overridepublic void onAnimationCancel()(Animation animation) {//監聽動畫被取消//對應animation.cancel()}@Overridepublic void onAnimationEnd(Animation animation) {//監聽動畫執行結束}});補間動畫的優缺點
優點:使用簡單,效果流暢,相比于逐幀動畫來說不用準備大量素材
缺點:作用于視圖對象View,未作用于屬性。即所有View的移動、隱藏、旋轉僅僅是看到的動畫效果,實際View的位置/大小/比例并沒有發生本質上的改變。
總結
以上是生活随笔為你收集整理的[0 to 0.5]从零开始学习Android动画知识(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux给GCC编译的应用程序创建服务
- 下一篇: 从零开始学习Android开发-Andr