標簽:tar rom develop shared pivot ted 組成 標簽 目錄
上篇文章介紹了應用程序內對用戶操作響應的相關方法位置,簡單的響應邏輯可以是從一個界面Activity
跳轉到另一個界面Activity
,也可以是某些視圖View
的相對變化。然而不管是啓動一個界面執行新界面Activity
的生命周期方法,還是視圖的相對變化,都需要一段時間,所以在響應的最終結果完成之前是有一段空白時間的。而在這段或長或短的時間裏,該怎麽給用戶展示界面呢?這就用到Android系統推薦的動畫流程了。
廣義上說,Android系統在屏幕上繪制展示給用戶的內容發生變化時,都可以使用相關動畫過渡。與用戶操作的響應一致,根據動畫的作用對象不同,展示動畫的效果可以作用于界面Activity
,也可以作用于視圖View
。大多文章是基于動畫分類的幀動畫、補間動畫介紹,而這裏將按照動畫的作用對象分別展開介紹。
視圖動畫可以作用于任何需要展示动画效果的视图View
,視圖動畫是Android系统最原生的一种动画类型,視圖動畫的定义类可以查看android.view.animation.Animation,其子类便是視圖動畫的效果分类,包括漸變效果AlphaAnimation
、旋轉效果RotateAnimation
、縮放效果ScaleAnimation
、移動效果TranslateAnimation
、和將上述多種效果集合到一起的合集效果AnimationSet
。
由于視圖View
既可以在布局文件中靜態聲明,也可以在代码中动态注册声明,所以类似的,視圖動畫的声明也可以分为在布局文件中靜態聲明,和在代碼中動態聲明两种方式。但是視圖動畫的效果启动使用,需要根据不同的用户响应决定,所以只能在代码中動態使用。由于視圖動畫可能包含大量的效果数据,所以一般推荐視圖動畫靜態聲明+動態使用的方式。
動態聲明的視圖動畫效果,只需要在代码中定义上述五种动画效果对应的动画类,并设置相关数据参数即可。其中
漸變效果AlphaAnimation (float fromAlpha, float toAlpha)必须要设置fromAlpha参数作为漸變效果的起始透明度,toAlpha参数作为漸變效果的结束透明度。
旋轉效果RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)必须要设置fromDegrees参数作为旋轉效果的起始旋转角度,和toDegrees参数作为旋轉效果的结束旋转角度;其他参数可选,包括屏幕坐标形式的后四个参数,pivotXType参数为pivotXValue参数类型,pivotXValue参数为绕x轴旋转的角度值,同理,pivotYType参数为pivotYValue参数类型,pivotYValue参数为绕y轴旋转的角度值。其中的参数类型包括Animation.ABSOLUTE
絕對類型,其參數值表示絕對數值;Animation.RELATIVE_TO_SELF
相對自身視圖類型,其參數值爲相對自身視圖在動畫效果前的百分值;Animation.RELATIVE_TO_PARENT
相對父視圖類型,其參數值爲相對父視圖在動畫效果前的百分值。
縮放效果ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)也是以屏幕坐标的形式记录参数,必须要设置fromX参数作为縮放效果开始时在x轴方向的比例,toX参数作为縮放效果结束时在x轴方向的比例,同理,fromY参数作为縮放效果开始时在y轴方向的比例,toY参数作为縮放效果结束时在y轴方向的比例;其他参数可选,其含义与旋轉效果的可选参数类似。
移動效果TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)和TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)同樣是以屏幕坐標的形式記錄參數,這兩個構造方法可以任選一種,其中當八參構造方法中的Type系列參數值爲Animation.RELATIVE_TO_SELF
時,Value系列參數所表示的數據與四參構造方法的Delta系列參數一致。
合集效果AnimationSet(boolean shareInterpolator)可以根據shareInterpolator參數決定該動畫內的一系列動畫展示時是否使用當前類對象中定義的插值器,之後可以調用該對象的addAnimation(Animation a)
依次放入要执行的系列視圖動畫對象。
這裏提到的插值器,是實現了android.view.animation.Interpolator接口的类,这些插值器类计算了視圖動畫效果中从开始到结束之间那段时间的效果展示,在上述視圖動畫效果Animation对象中,可以通过调用setInterpolator(Interpolator i)
方法設置,如果不設置會默認使用android.view.animation.LinearInterpolator線性插值器。
上述五種效果類的構造方法中,還有一種(Context context, AttributeSet attrs)
参数的构造方法,使用该构造方法可以通过参数二attrs传入靜態聲明的动画资源文件,从而在代码中使用实例化對象。
靜態聲明的視圖動畫文件,必须保存在res/anim/资源目錄下,符合xml格式的文件。该文件的根標簽必须是五种視圖動畫效果之一,包括漸變效果<alpha></alpha>
、旋轉效果<scale></scale>
、縮放效果<rotate></rotate>
、移動效果<translate></translate>
、合集效果<set></set>
。而其中的必選參數和可選參數也都與代碼動態聲明中的相對應。
最终都可以在代码中得到上述五种視圖動畫类的实例化對象。可以调用setAnimationListener(Animation.AnimationListener listener)
設置動畫執行的監聽,在實現的android.view.animation.Animation.AnimationListener接口實例中,可以分別實現onAnimationStart(Animation animation)
動畫開始前、onAnimationRepeat(Animation animation)
動畫重複時、onAnimationEnd(Animation animation)
動畫結束時的回調監聽。在啓動動畫展示的地方,調用startNow()
方法可以立即開始;或者先調用setStartTime(long startTimeMillis)
設置啓動的延時時間,再調用start()
方法開始計時,等延時時間之後開始展示動畫。
在AndroidSDK提供的系統視圖中,有一種類似幕布繪制圖像的系列視圖,像android.widget.ImageView,这种具有绘制像素位图功能的视图,更适合在其中绘制展示多张图片连续组合的帧动画。本质上圖片動畫只是一系列图片的组合,所以其声明和使用方式更随意,不仅可以在代码中動態聲明+動態使用的方式,也可以直接在資源文件中靜態聲明+靜態使用。不过因为圖片動畫需要加载大量的图片,所以在代码中動態聲明使用的方式是在应用程序运行过程中执行的,可能会影响用户的流畅度,所以推荐圖片動畫使用靜態聲明+靜態使用的方式。
動態聲明的圖片動畫可以使用android.graphics.drawable.AnimationDrawable类实例化加载位图組成的帧动画。之后依次调用该对象的addFrame(Drawable frame, int duration)
方法增加要展示的每一幀圖片,其中參數一frame
即指定了要加載的圖片資源,參數二duration
則表示當前圖片資源幀在整個動畫播放中的時長,單位是毫米。也可以調用該對象的setOneShot(boolean oneShot)
设置当前系列帧的圖片動畫是否只播放一遍。最终在需要启动圖片動畫的位置,调用该对象的start()
,而在需要停止圖片動畫的位置,调用对象的stop()
。
这里需要注意的是,圖片動畫启动的
start()
方法必須要在界面Activity
的聲明周期方法執行完onCreate()
之後調用。
靜態聲明的圖片動畫文件,必须保存在res/drawable/目錄下,符合xml格式的文件。该文件的根標簽必须是<animation-list></animation-list>
,在该標簽中可以使用android:oneshot
屬性值爲true
或false
,来表示当前系列帧的圖片動畫是否只播放一遍。而其中的每一帧图片使用<item />
中的android:drawable
屬性值作爲drawable
資源文件引用,同時要通過android:duration
屬性值設置當前圖片幀的展示時長,根據人眼的識別速度,通常設置在1000(單位毫秒)以下。之後如果想靜態使用,可以在要顯示動畫的視圖中,通過設置其android:backgroud
屬性,並將靜態聲明的資源文件名作爲drawable
資源類型賦值,即可關聯使用。如果想動態使用,首先在代碼中找到要顯示動畫的視圖對應的對象,調用該對象的setBackgroundResource(int res)
,同樣將靜態聲明的資源文件名作爲R.drawable
资源类型赋值,也可关联使用。最终,在需要启动圖片動畫的代码中,通过调用视图对象的getBackgroud()
方法获取到圖片動畫的接口android.graphics.drawable.Animatable对象,就可以在需要启动和停止圖片動畫的位置分别调用start()
和stop()
方法。
另外, 在Android5.0 即API 21及以上的版本中,通过在项目modle中增加项目依赖库support-vector-drawable和animated-vector-drawable,以支持在资源文件中定义绘制矢量图,在AndroidStudio创建默认项目时,所使用的默认应用icon就是矢量图对象,其优势就是缩放仍不失真、体积小等,这里不详介绍。针对这种矢量图对象,也可以更加快速的增加矢量圖動畫。由于矢量图只能在资源文件中靜態聲明,相应的,矢量圖動畫也只能在资源文件中靜態聲明。這種動畫效果主要依賴于android.graphics.drawable.AnimatedVectorDrawable類或最新包向下兼容的androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat類。
矢量圖的聲明是在res/drawable/
资源目錄下,以<vector></vector>
標簽所包裹的一层表示普通矢量图,可以在该標簽内部增加<group></group>
標簽包裹一组动画效果,设置其android:name
属性标记该组动画名称,同时使用視圖動畫相关屬性值作爲視圖動畫效果展示,包括渐变、旋转、缩放、平移。也可以在<group>
標簽内部,继续使用<path></path>
標簽定义一系列路径,同样需要设置其android:name
屬性標記該組路徑名稱。
矢量動畫的聲明是在res/animator/
资源目錄下,以<objectAnimator></objectAnimator>
为根標簽包裹的动画效果,通过设置其android:propertyName
属性值,可以描述視圖動畫效果中的渐变、缩放、旋转、平移等效果,其内部属性与靜態聲明的視圖動畫中的属性类似。而以<set></set>
为根標簽则可以包裹一系列上述四种动画效果所表示的<objectAnimator></objectAnimator>
標簽。
最後是將矢量圖與矢量動畫關聯使用,需要在res/drawable
资源目錄下创建新的xml资源文件,以<animated-vector></animated-vector>
作为根標簽,并设置其android:drawable
屬性並引用上述普通矢量圖資源文件爲drawable
资源类型赋值。在根標簽内通过<target android:name="" android:animation="" />
分別爲矢量圖定義中的android:name
屬性值與矢量圖聲明中的資源文件相關聯。最終在引用普通矢量圖資源文件的位置改爲引用動畫矢量圖資源文件。
界面動畫仅在Android5.0即 API 21 及以上的版本中支持。界面動畫作用于界面Activity
,只有在兩個界面Activity
相互启动切换时,才需要展示界面動畫,因此界面動畫的展示对象主要分三种,包括作为舊界面Activity
在退出時動畫效果,作爲新界面Activity
在進入動畫效果,和兩個界面之間如果有相同內容的同類視圖,稱之爲共享視圖,其在界面切換時的動畫效果。而關于這些對象的動畫效果,AndroidSDK提供了一些統一的動畫效果可供選擇,包括針對退出和進入動畫的淡入淡出效果的android.transition.Fade类、移動效果android.transition.Slide類、爆炸效果android.transition.Explode类;还有针对共享視圖的視圖動畫效果。或者也可以继承android.transition.Transition實現自定義動畫效果。
由于界面Activity
的定义是在清单文件中静态注册的,所以界面動畫的使用也可以在注册时采用靜態聲明使用的方式。在靜態使用时用到了<activity android:style/>
樣式屬性,該屬性值是已經定義了<style></style>
標簽的xml格式的样式资源文件。在<style>
样式標簽中,必须包含属性parent="android:Theme.Material"
或其子樣式名。
要想启动界面動畫,首先在该样式中增加一条开关控制。
<item name="android:windowActivityTransitions">true</item>
之后重写该样式標簽中的<item>
標簽,根据name
屬性值控制不同的動畫對象,而根據<item></item>
標簽值指定不同的动画效果。这里将不同動畫對象对应关系列为下列表格。
動畫對象 | name值 |
---|---|
作爲新界面進入動畫 | android:windowEnterTransition |
作为舊界面退出动画 | android:windowExitTransition |
作为新界面进入时共享視圖動畫 | android:windowSharedElementEnterTransition |
作为舊界面退出时共享視圖動畫 | android:windowSharedElementExitTransition |
既然界面動畫是通过样式定义的方式靜態聲明,那肯定也能在界面Activity
創建後的方法回調中通過代碼動態聲明使用。這裏用到了android.view.Window類,因爲樣式的修改要在界面加載布局之前,所以在setContentView()
方法之前,通過調用getWindow()
方法可以得到Window
對象。
首先同樣需要調用該對象的requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
方法开启界面動畫开关。
之后调用该对象的系列方法来控制不同動畫對象,根据传入的Transition
对象的实例指定不同的动画效果。不同動畫對象的对应关系如下表。
動畫對象 | Window類調用方法 |
---|---|
作爲新界面進入動畫 | setEnterTransition() |
作为舊界面退出动画 | setExitTransition() |
作为新界面进入时共享視圖動畫 | setSharedElementEnterTransition() |
作为舊界面退出时共享視圖動畫 | setSharedElementExitTransition() |
针对共享視圖的动画,还需要分别在两个布局文件中标记共享視圖,使用android:transitionName
属性指定相同的共享視圖名字。
在声明界面動畫效果后,还需要在该界面作为新界面被启动的位置或者该界面作为舊界面启动其他界面的位置,将原有的startActivity(Intent intent)
方法修改爲startActivity(Intent intent, Bundle bundle)
方法。其中的intent
參數還是之前要啓動界面的意圖信息,bundle
参数则是新增的控制界面動畫的数据包。可以通过ActivityOptions.makeSceneTransitionAnimation(this).toBundle()
系列方法获取当前界面声明的界面動畫效果,其结果值作为android.os.Bundle對象傳入即可。
如果在界面動畫中有单个共享視圖動畫,可以参考
ActivityOptions.makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)
方法。
如果在界面動畫中有多个共享視圖動畫,可以参考
ActivityOptions.makeSceneTransitionAnimation(Activity activity, Pair...<View, String> sharedElements)
方法。
除了上面作用于三種對象的基本動畫類型,Android系統還提供了一種作用于任何對象的屬性動畫,該動畫具有更全面的功能,詳情可期待下篇文章。
Android系統編程入門系列之界面Activity響應絲滑的傳統動畫
標簽:tar rom develop shared pivot ted 組成 標簽 目錄
原文地址:https://www.cnblogs.com/BobGo/p/15032288.html