android 从底部网上的平移动画_Android属性动画,看完这篇够用了吧
轉載自作者新小夢
隨著APP的開發周期演進,APP不再滿足基礎的功能保障,需要有較好視覺體驗和交互操作。那么動畫效果是必不可少的,動畫有幀動畫,補間動畫,屬性動畫等等。
本文通過一些簡單常見的動畫效果,和大家重溫屬性動畫的相關知識點。旨在通過全文,全面掌握屬性動畫~如果看完本文,還需要查閱其他文章,說明本文總結得還不夠好,歡迎留言補充。
一、屬性動畫概覽
顧名思義,通過控制對象的屬性,來實現動畫效果。官方定義:定義一個隨著時間 (注:停個頓)更改任何對象屬性的動畫,無論其是否繪制到屏幕上。
可以控制對象什么屬性呢?什么屬性都可以,理論是通過set和get某個屬性來達到動畫效果。例如常用下面一些屬性來實現View對象的一些動畫效果。
- 位移:translationX、translationY、translationZ
- 透明度:alpha,透明度全透明到不透明:0f->1f
- 旋轉:rotation,旋轉一圈:0f->360f
- 縮放:水平縮放scaleX,垂直縮放scaleY
簡單的效果圖:
二、基本使用
簡單介紹View對象幾個屬性動畫的使用。
1、位移屬性動畫
效果圖:
先看一下布局代碼的實現:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/colorPrimary"><LinearLayoutandroid:id="@+id/llAddAccount"android:layout_width="wrap_content"android:layout_height="35dp"android:layout_alignParentRight="true"android:layout_marginTop="100dp"android:layout_marginRight="-70dp"//將現有視圖藏在屏幕的右邊android:background="@drawable/bg_10_10_fff"><ImageViewandroid:id="@+id/ivMakeNote"android:layout_width="35dp"android:layout_height="30dp"android:layout_gravity="center_vertical"android:paddingLeft="2dp"android:paddingTop="2dp"android:paddingBottom="2dp"android:src="@mipmap/ic_account_add" /><TextViewandroid:id="@+id/tvAddAccount"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center_vertical"android:paddingRight="12dp"android:text="添加賬戶"android:textColor="@color/colorPrimary"android:textSize="14sp" /></LinearLayout> </RelativeLayout>上面只是簡單實現了布局,下面看看屬性動畫代碼的實現:
llAddAccount.setOnClickListener {val objectAnimation =ObjectAnimator.ofFloat(llAddAccount, "translationX", 0f, -70f)objectAnimation.start() }到這里,我們才真正看到屬性動畫的影子。通過ObjectAnimator的工廠方法ofFloat我們得到一個ObjectAnimator對象,并通過該對象的start()方法,開啟動畫效果。
ofFloat()方法的第一個參數為要實現動畫效果的View,例如這里整體效果的LinearLayout;第二個參數為屬性名,也就是前面所說的:translationX,translationY,alpha,rotation,scaleX,scaleY等,這里要實現的是水平平移效果,所以我們采用了translationX;第三參數為可變長參數,第一個值為動畫開始的位置,第二個值為結束值得位置,如果數組大于3位數,那么前者將是后者的起始位置。
注意事項:如果可變長參數只有一個值,那么ObjectAnimator的工廠方法會將值作為動畫結束值,此時屬性必須擁有初始化值和getXXX方法。
translationX和translationY這里涉及到的位移都是相對自身位置而言。例如 View在點A(x,y)要移動到點B(x1,y1),那么ofFloat()方法的可變長參數,第一個值應該0f,第二個值應該x1-x。
XML布局實現:
在res/animator文件夾下,創建animator_translation.xml文件,內容如下:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:propertyName="translationX"android:valueFrom="0dp"android:valueTo="-70dp"android:valueType="floatType" />在代碼上調用:
llAddAccount.setOnClickListener {val objectAnimation =AnimatorInflater.loadAnimator(this,R.animator.animator_translation)objectAnimation.setTarget(llAddAccount)objectAnimation.start() }2、透明屬性動畫
透明度屬性動畫比較簡單,即控制View的可見度實現視覺差動畫效果。這里展示效果是從不透明到透明,再到不透明。
代碼如下:
tvText.setOnClickListener {val objectAnimation =ObjectAnimator.ofFloat(tvText, "alpha", 1f,0f,1f)objectAnimation.duration=3000objectAnimation.start() }ofFloat()方法將屬性名換成了透明度alpha,并且可變長參數增加到了3個。給ObjectAnimator對象的duration屬性設置了動畫展示時間3秒,默認情況下300毫秒。
3、縮放屬性動畫
縮放可以通過控制scaleX和scaleY分別在X軸和Y軸上進行縮放,如下圖在X軸中進行兩次兩倍縮放。
代碼如下:
tvText.setOnClickListener {val objectAnimation =ObjectAnimator.ofFloat(tvText, "scaleX", 1f,2f)objectAnimation.duration=3000objectAnimation.repeatCount=2objectAnimation.repeatMode=ValueAnimator.REVERSEobjectAnimation.start() }ofFloat()方法傳入參數屬性為scaleX和scaleY時,動態參數表示縮放的倍數。設置ObjectAnimator對象的repeatCount屬性來控制動畫執行的次數,設置為ValueAnimator.INFINITE表示無限循環播放動畫;通過repeatMode屬性設置動畫重復執行的效果,取值為:ValueAnimator.RESTART和ValueAnimator.REVERSE。
ValueAnimator.RESTART效果:(即每次都重頭開始)
ValueAnimator.REVERSE效果:(即和上一次效果反著來)
4、旋轉屬性動畫
旋轉動畫也比較簡單,將一個View進行順時針或逆時針旋轉。
代碼如下
tvText.setOnClickListener {val objectAnimation =ObjectAnimator.ofFloat(tvText, "rotation", 0f,180f,0f)objectAnimation.duration=3000objectAnimation.start() }ofFloat()方法的可變長參數,如果后者的值大于前者,那么順時針旋轉,小于前者,則逆時針旋轉。
三、AnimatorSet
如果想要一個動畫結束后播放另外一個動畫,或者同時播放,可以通過AnimatorSet來編排。
val aAnimator=ObjectAnimator.ofInt(1) val bAnimator=ObjectAnimator.ofInt(1) val cAnimator=ObjectAnimator.ofInt(1) val dAnimator=ObjectAnimator.ofInt(1)AnimatorSet().apply {play(aAnimator).before(bAnimator)//a 在b之前播放play(bAnimator).with(cAnimator)//b和c同時播放動畫效果play(dAnimator).after(cAnimator)//d 在c播放結束之后播放start() }或者
AnimatorSet().apply {playSequentially(aAnimator,bAnimator,cAnimator,dAnimator) //順序播放start() }AnimatorSet().apply {playTogether(animator,bAnimator,cAnimator,dAnimator) //同時播放start() }另有:
AnimatorSet ().apply {play(aAnimator).after(1000) //1秒后播放a動畫start() }四、ViewPropertyAnimator
如果只是針對View對象的特定屬性同時播放動畫,我們也可以采用ViewPropertyAnimator。
例如:
tvText.animate().translationX(100f).translationY(100f).start()支持屬性:
- translationX、translationY、translationZ
- x、y、z
- alpha
- scaleX、scaleY
注意到ViewPropertyAnimator對象具有property(Float)和propertyBy(Float)方法,其中property(Float)是指屬性變化多少(可以理解一次有效),而propertyBy(Float)每次變化多少(可以理解多次有效)。
舉例說明:
translationX
tvText.setOnClickListener {val animator = tvText.animate()animator.duration=1000animator.translationX(100f)//點擊一次會向右偏移,再點擊沒效果animator.start() }translationXBy
tvText.setOnClickListener {val animator = tvText.animate()animator.duration=1000animator.translationXBy(100f)//每次點擊都會向右偏移animator.start() }五、ValueAnimator與ObjectAnimator
ValueAnimator作為ObjectAnimator的父類,主要動態計算目標對象屬性的值,然后設置給對象屬性,達到動畫效果,而ObjectAnimator則在ValueAnimator的基礎上極大地簡化對目標對象的屬性值的計算和添加效果,融合了 ValueAnimator 的計時引擎和值計算以及為目標對象的命名屬性添加動畫效果這一功能。
舉個栗子,通過ValueAnimator的工廠方法ofFloat、ofInt、ofArgb、ofObject來實現動畫效果:
代碼如下:
//ValueAnimator實現tvText.setOnClickListener {val valueAnimator = ValueAnimator.ofFloat(0f, 180f)valueAnimator.addUpdateListener {tvText.rotationY = it.animatedValue as Float //手動賦值}valueAnimator.start()}//ObjectAnimator實現ObjectAnimator.ofFloat(tvText, "rotationY", 0f, 180f).apply { start() }從上面代碼可以看出,使用ValueAnimator實現動畫,需要手動賦值給目標對象tvText的rotationY,而ObjectAnimator則是自動賦值,不需要手動賦值就可以達到效果。
動畫過程可以通過AnimatorUpdateListener和AnimatorListener來監聽。
ObjectAnimator.ofFloat(tvText, "translationX", 0f, 780f, 0f).apply {duration=3000//完成動畫所需要時間repeatCount=ValueAnimator.INFINITE //重復次數:無限循環repeatMode=ValueAnimator.RESTART //重復模式:重頭開始addUpdateListener { //監聽值變化tvText.translationX= it.animatedValue as Float}addListener(object:Animator.AnimatorListener{override fun onAnimationRepeat(animation: Animator?) {//動畫重復}override fun onAnimationEnd(animation: Animator?) {//動畫結束}override fun onAnimationCancel(animation: Animator?) {//動畫取消}override fun onAnimationStart(animation: Animator?) {//動畫開始}})}動畫可調用start()方法開始,也可調用cancel()方法取消。
那么,要正確使屬性動畫實現動畫效果,那么目標對象應該注意什么?
- 屬性必須具有 set<PropertyName>() 形式的 setter 函數(采用駝峰式大小寫形式),例如,如果屬性名稱為 text,則需要使用 setText() 方法。
- 如果ObjectAnimator的一個工廠方法中僅為 values... 參數指定了一個值,那么該參數需要提供初始值和getPropertyName()方法。
- 屬性的初始值和結束值之間必須保持類型相同。
- 可能需要在UpdateListener對象中調用invalidate() 方法,來刷新屬性作用后的效果。
六、XML實現
本文一開始介紹位移屬性動畫時,有提到通過XML文件來實現動畫效果,在這里進一步細講。
在res/animator文件夾下,創建animator_translation.xml文件。XML文件有四個標簽可用,要注意到propertyValuesHolder標簽的Android 版本適配。
<?xml version="1.0" encoding="utf-8"?> <set> =>AnimatorSet<animator/> =>ValueAnimator<objectAnimator> =>ObjectAnimator<propertyValuesHolder/> =>PropertyValuesHolder</objectAnimator> </set>set標簽對應代碼的AnimatorSet,只有一個屬性可以設置:android:ordering,取值:同時播放together、順序播放sequentially。
animator標簽對應代碼的ValueAnimator,可以設置如下屬性:
- android:duration:動畫時長
- android:valueType:屬性類型,intType、floatType、colorType
- android:valueFrom:屬性初始值
- android:valueTo:屬性結束值
- android:repeatCount:重復次數
- android:repeatMode:重復模式
- android:interpolator:插值器,可看下一節默認插值器。
- android:startOffset:延遲,對應startOffset()延遲多少毫秒執行
示例:
<animatorandroid:duration="1000"android:valueType="floatType"android:valueFrom="0f"android:valueTo="100f"android:repeatCount="infinite"android:repeatMode="restart"android:interpolator="@android:interpolator/linear"android:startOffset="100"/>objectAnimator屬性對應代碼ObjectAnimator,由于繼承自ValueAnimator,所以屬性相對多了` android:propertyName。
七、估值器與插值器
看到這里,不知道小伙伴們有沒有這個疑問,屬性動畫是如何計算屬性的值的?
這份工作由類型估值器TypeEvaluator與時間插值器TimeInterpolator來完成的。
插值器:根據時間流逝的百分比計算出當前屬性值改變的百分比。
估值器:根據當前屬性改變的百分比來計算改變后的屬性值。
從它兩的已定義,也可以看出它們之間的協調關系,先由插值器根據時間流逝的百分比計算出目標對象的屬性改變的百分比,再由估值器根據插值器計算出來的屬性改變的百分比計算出目標對象屬性對應類型的值。
從估值器和插值器可以看出屬性動畫的工作原理,下面看看官方對工作原理的解析:
估值器
SDK中默認帶有的估值器有: IntEvaluator、FloatEvaluator、ArgbEvaluator,他們分別對應前面我們調用 ValueAnimator對象所有對應的ofInt、ofFloat、ofArgb函數的估值器,分別用在Int類型,Float,顏色值類型之間計算。而ofObject函數則對應我們自定義類型的屬性計算。
當估值器的類型不滿足需求,就需要自定義類型估值器。例如我們要實現下面效果:
這個效果可以通過AnimatorSet來實現,但我們這里采用自定義TypeEvaluator來實現TextView從屏幕左上角斜線滑到屏幕右下角。
一個簡單的自定義估值器就算完成了。數學學的好,任何復雜效果都不是問題。
插值器
TypeEvaluator對象的evaluate()方法的fraction參數就是插值器計算得來,SDK中默認的時間插值器有:
- LinearInterpolator 線性(勻速)
- AccelerateInterpolator 持續加速
- DecelerateInterpolator 持續減速
- AccelerateDecelerateInterpolator 先加速后減速
- OvershootInterpolator 結束時回彈一下
- AnticipateInterpolator 開始回拉一下
- BounceInterpolator 結束時Q彈一下
- CycleInterpolator 來回循環
看看效果:
LinearInterpolator
AccelerateInterpolator
DecelerateInterpolator
AccelerateDecelerateInterpolator
OvershootInterpolator
AnticipateInterpolator
BounceInterpolator
CycleInterpolator
正常情況下,默認的插值器已經夠用,如果自己數學厲害,想顯擺一下,也是通過實現TimeInterpolator接口的getInterpolation()自定義的。
/*** A time interpolator defines the rate of change of an animation. This allows animations* to have non-linear motion, such as acceleration and deceleration.*/ public interface TimeInterpolator {/*** Maps a value representing the elapsed fraction of an animation to a value that represents* the interpolated fraction. This interpolated value is then multiplied by the change in* value of an animation to derive the animated value at the current elapsed animation time.** @param input A value between 0 and 1.0 indicating our current point* in the animation where 0 represents the start and 1.0 represents* the end* @return The interpolation value. This value can be more than 1.0 for* interpolators which overshoot their targets, or less than 0 for* interpolators that undershoot their targets.*/float getInterpolation(float input); }八、Keyframe
要控制動畫速率的變化,就得去自定義插值器或估值器,對我這種數學渣渣來說,簡直比上天一樣難的。
所以渣渣們可以考慮用關鍵幀Keyframe對象來實現。Keyframe讓我們可以指定某個屬性百分比時對象的屬性值。
tvText.setOnClickListener {val start = Keyframe.ofFloat(0f, 0f)val middle = Keyframe.ofFloat(0.3f, 400f)val end = Keyframe.ofFloat(1f, 700f)val holder=PropertyValuesHolder.ofKeyframe("translationX",start,middle,end)ObjectAnimator.ofPropertyValuesHolder(tvText,holder).apply {duration=2000start()}}上面代碼分別定義了三個關鍵幀,分別在屬性百分比為0f、0.3f、1f對應的translationX的值。
動畫效果:
可以看到效果先快后慢。
Keyframe同樣支持ofFloat、ofInt、ofObject。使用關鍵幀,至少需要有兩個關鍵幀,不然坐等崩潰吧。PropertyValuesHolder對象是用來保存動畫過程所操作的屬性和對應的值。
九、總結
通過ObjectAnimator的工廠方法可以快速實現一個屬性動畫,但默認的屬性動畫不滿足自己的需求是,可以通過ValueAnimator對象來定義自己的屬性,注意屬性的要求。可以通過AnimatorSet來實現屬性組合播放效果。
動畫的原理是通過時間插值器與類型估值器配置使用,控制對象的屬性來實現動畫效果。
總結
以上是生活随笔為你收集整理的android 从底部网上的平移动画_Android属性动画,看完这篇够用了吧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: es6 混合commjs_详谈commo
- 下一篇: c++ 遍历所有点且距离最短_L3图论第