Google除了提供了屬性動畫之外,還提供了一種基於物理的動畫,叫做DynamicAnimation,與物理世界更貼近,關於這塊可以參考https://www.jianshu.com/p/46b1cdc253e9。
目前主要有兩種DynamicAnimation,分別是:
-
Spring Animation 類比彈力
-
Fling Animation 類比速度、動量
本文主要介紹Fling Animation。話不多說,先看下官方demo示例:
在鬆手後,會繼續有動畫的效果,逐漸減慢直至停止,是不是和現實生活中很類似?因為有摩擦力,所以會不斷減少,這時高中老師教給我們的牛頓力學可以發揮用場了。
再來看下本文最終的demo示例:
拖動ImageView,鬆手的一瞬間,如果垂直方向的加速度大於水平方向的,那麼垂直方向進行動畫;反之水平方向運動,運動範圍限制在螢幕中。
FlingAnimation的使用
FlingAnimation的使用主要分為兩步驟:
- 新增支援庫
dependencies {
implementation 'com.android.support:support-dynamic-animation:28.0.0'
}
複製程式碼
- 建立一個FlingAnimation
val fling = FlingAnimation(view, DynamicAnimation.SCROLL_X)
複製程式碼
FlingAnimation的建立需要指定View以及動畫的屬性,接下來就是設定一些屬性,
- setStartVelocity(float):設定起始加速度,單位是改變的屬性每秒,預設是0。如果需要使用dp轉pixel,可以使用下段程式碼:
float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond,
getResources().getDisplayMetrics());
複製程式碼
- setMinValue(float):設定動畫的最小值。這個值是建立FlingAnimation中的屬性值的最小值,也就是說屬性值不過小於該值。
- setMaxValue(float):與上面類似,只不過是最大值,min<=屬性值<=max。
- setFriction(float):設定摩擦力,學過力學的都知道,沒有摩擦力,那麼將一直運動下去;而摩擦力越大,那麼將會越快停止,預設值是1。
- setMinimumVisibleChange(float):當建立一個單位不是pixel的自定義屬性時,需要設定該值;DynamicAnimation.ViewProperty裡面的屬性是不需要設定該值的。
Demo示例程式碼
學完了理論知識,就看一下程式碼了,佈局很簡單,就一個ImageView,將touch事件交給了GestureDetector,然後在onFling()方法中實現FlingAnimation動畫;有一點需要注意的是,FlingAnimation改變的是transitionX和transitionY屬性,為了限制在螢幕內動畫,因此計算了x和y方向的最大值,具體程式碼如下:
class FlingAnimationActivity : AppCompatActivity() {
lateinit var gestureDetector: GestureDetector
var maxTransitionX: Int? = null
var maxTransitionY: Int? = null
private val gestureListener = object : GestureDetector.SimpleOnGestureListener() {
override fun onDown(e: MotionEvent?): Boolean {
return true
}
override fun onFling(e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean {
if (Math.abs(velocityX) > Math.abs(velocityY)) {
FlingAnimation(ivImg, DynamicAnimation.TRANSLATION_X).apply {
setStartVelocity(velocityX)
setMinValue(0f)
setMaxValue(maxTransitionX!!.toFloat())
friction = 1.1f
start()
}
} else {
FlingAnimation(ivImg, DynamicAnimation.TRANSLATION_Y).apply {
setStartVelocity(velocityY)
setMinValue(0f)
setMaxValue(maxTransitionY!!.toFloat())
friction = 1.1f
start()
}
}
return true
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fling)
mainLayout.viewTreeObserver.addOnGlobalLayoutListener {
maxTransitionX = mainLayout.width - ivImg.width
maxTransitionY = mainLayout.height - ivImg.height
}
gestureDetector = GestureDetector(this, gestureListener)
ivImg.setOnTouchListener { v, event ->
gestureDetector!!.onTouchEvent(event)
}
}
}
複製程式碼
參考文章
- developer.android.com/guide/topic…
- developer.android.com/reference/a…
- proandroiddev.com/introductio…
- medium.com/@temidjoy/a…
- www.jianshu.com/p/46b1cdc25…
關注我的技術公眾號,不定期會有技術文章推送,不敢說優質,但至少是我自己的學習心得。微信掃一掃下方二維碼即可關注: