溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)

發(fā)布時(shí)間:2021-10-25 16:10:05 來源:億速云 閱讀:136 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

彈性與阻尼

物理動(dòng)畫,顧名思義是基于物理學(xué)定律基礎(chǔ)的動(dòng)畫效果,它實(shí)際上參考的就是彈簧的形變過程,即胡克定律,這種動(dòng)畫類型,通常被稱為Spring Animation。官網(wǎng)上其實(shí)在很不起眼的小角落有一篇非常詳細(xì)的文檔,如下所示。

https://developer.android.com/guide/topics/graphics/spring-animation#add-support-library

對(duì)于Spring Animation來說,通常有兩種常用的場(chǎng)景,即彈性和阻尼,彈性定義的是物體恢復(fù)到某個(gè)狀態(tài)下的非線性過程,而阻尼,則定義的是拖動(dòng)物體的非線性阻力。

關(guān)于Spring的設(shè)計(jì)定義,大家可以參考下這篇文章 https://zhuanlan.zhihu.com/p/127266926。

 

彈性

首先,我們來看下彈性的實(shí)現(xiàn)。首先,需要引入Google的Spring實(shí)現(xiàn)庫,代碼如下所示。

api 'androidx.dynamicanimation:dynamicanimation:1.0.0'
 

要使用Spring Animation其實(shí)非常簡(jiǎn)單,定義SpringAnimation即可,甚至不用設(shè)置參數(shù),下面就通過一個(gè)最簡(jiǎn)單的示例,來演示下如何使用Spring Animation,代碼如下所示。

class MainActivity : AppCompatActivity() {
    var offsetX: Float = 0f
    var offsetY: Float = 0f

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        test.setOnTouchListener { v, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    offsetX = event.rawX
                    offsetY = event.rawY
                }
                MotionEvent.ACTION_MOVE -> {
                    test.translationX = event.rawX - offsetX
                    test.translationY = event.rawY - offsetY
                }
                MotionEvent.ACTION_UP -> {
                    SpringAnimation(test, DynamicAnimation.TRANSLATION_Y).apply {
                        spring = SpringForce().apply {
//                            dampingRatio = DAMPING_RATIO_NO_BOUNCY
//                            stiffness = SpringForce.STIFFNESS_VERY_LOW
                        }
                        animateToFinalPosition(0f)
                    }
                    SpringAnimation(test, DynamicAnimation.TRANSLATION_X).apply {
                        spring = SpringForce().apply {
//                            dampingRatio = DAMPING_RATIO_NO_BOUNCY
//                            stiffness = SpringForce.STIFFNESS_VERY_LOW
                        }
                        animateToFinalPosition(0f)
                    }
                }
            }
            true
        }
    }
}
 

上面的代碼定義了一個(gè)可以拖動(dòng)并改變位置的View,當(dāng)執(zhí)行ACTION_UP的時(shí)候,就會(huì)執(zhí)行定義的SpringAnimation,SpringAnimation需要幾個(gè)參數(shù),即TargetView、執(zhí)行動(dòng)畫的屬性、以及最終的屬性值,而動(dòng)畫,則可以通過調(diào)用start(),或調(diào)用animateToFinalPosition()方法來啟動(dòng),它們的區(qū)別就是是否設(shè)置了finalPosition,效果如圖所示。

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
slide-min

很簡(jiǎn)單的幾行代碼就實(shí)現(xiàn)了彈性的效果。

 

哪些屬性

基于Spring特性的動(dòng)畫可以更改屏幕上的View的實(shí)際屬性,從而為View添加動(dòng)畫效果。系統(tǒng)中支持了下面這些屬性。

  • ALPHA:表示視圖的 Alpha 透明度。該值默認(rèn)為 1(不透明),值為 0 則表示完全透明(不可見)。
  • TRANSLATION_X、TRANSLATION_Y 和 TRANSLATION_Z:這些屬性用于控制視圖所在的位置,值為視圖的布局容器所設(shè)置的左側(cè)坐標(biāo)、頂部坐標(biāo)和高度的增量。
  • TRANSLATION_X 表示左側(cè)坐標(biāo)。
  • TRANSLATION_Y 表示頂部坐標(biāo)。
  • TRANSLATION_Z 表示視圖相對(duì)于其高度的深度。
  • ROTATION、ROTATION_X 和 ROTATION_Y:這些屬性用于控制視圖圍繞軸心點(diǎn)進(jìn)行的 2D(rotation屬性)和 3D 旋轉(zhuǎn)。
  • SCROLL_X 和 SCROLL_Y:這些屬性分別表示視圖距離源左側(cè)和頂部邊緣的滾動(dòng)偏移量(以像素為單位)。它還以頁面滾動(dòng)的距離來表示位置。
  • SCALE_X 和 SCALE_Y:這些屬性用于控制視圖圍繞其軸心點(diǎn)進(jìn)行的 2D 縮放。X、Y 和 Z:這些是基本的實(shí)用屬性,用于描述視圖在容器中的最終位置。
  • X 是左側(cè)值與 TRANSLATION_X 的和。
  • Y 是頂部值與 TRANSLATION_Y 的和。
  • Z 是高度值與 TRANSLATION_Z 的和。

實(shí)際上與屬性動(dòng)畫的默認(rèn)屬性值基本是一致的,其本質(zhì),也是借助了屬性動(dòng)畫來實(shí)現(xiàn)Spring效果。

 

監(jiān)聽

與屬性動(dòng)畫一樣,Spring Animation同樣可以監(jiān)聽其動(dòng)畫的生命周期,系統(tǒng)提供了OnAnimationUpdateListener和OnAnimationEndListener,來監(jiān)聽動(dòng)畫。

通過addUpdateListener來設(shè)置,代碼如下所示。

anim.addUpdateListener { _, value, _ -> anim.animateToFinalPosition(value) }
 

與之對(duì)應(yīng)的,系統(tǒng)提供了removeUpdateListener() 和 removeEndListener()方法來移除監(jiān)聽。

 

SpringForce

對(duì)應(yīng)一個(gè)彈性系統(tǒng)來說,SpringForce是描述該彈性系統(tǒng)的各種參數(shù)的封裝。

SpringForce:定義動(dòng)畫具有的彈簧特征。其中有四個(gè)關(guān)鍵的參數(shù):

  • finalPosition:靜止位置。

  • stiffness:即彈簧常數(shù),物體的彈性系數(shù)。

  • dampingRatio:阻尼比。描述系統(tǒng)擾動(dòng)后的振蕩衰減過程。

  • velocity:運(yùn)動(dòng)的初速度。

在這四個(gè)參數(shù)中,finalPosition用于描述動(dòng)畫最終停止的位置,而velocity則是描述物體運(yùn)動(dòng)的初速度,默認(rèn)情況下,velocity為0,系統(tǒng)提供了setStartVelocity()方法來改變這個(gè)初速度,在大部分情況下,我們都不用修改。

剩下兩個(gè)屬性stiffness和dampingRatio,則是Spring Animation的核心配置參數(shù)。

 

阻尼比dampingRatio

阻尼比用于描述彈簧振動(dòng)逐漸衰減的狀況。通過使用阻尼比,可以定義振動(dòng)從一次彈跳到下一次彈跳所衰減的速度有多快。

  • 當(dāng)阻尼比大于 1 時(shí),會(huì)出現(xiàn)過阻尼現(xiàn)象。它會(huì)使對(duì)象快速地返回到靜止位置。
  • 當(dāng)阻尼比等于 1 時(shí),會(huì)出現(xiàn)臨界阻尼現(xiàn)象。這會(huì)使對(duì)象在最短時(shí)間內(nèi)返回到靜止位置。
  • 當(dāng)阻尼比小于 1 時(shí),會(huì)出現(xiàn)欠阻尼現(xiàn)象。這會(huì)使對(duì)象多次經(jīng)過并越過靜止位置,然后逐漸到達(dá)靜止位置。
  • 當(dāng)阻尼比等于零時(shí),便會(huì)出現(xiàn)無阻尼現(xiàn)象。這會(huì)使對(duì)象永遠(yuǎn)振動(dòng)下去。

一般來說,首先需要調(diào)用getSpring()方法來獲取當(dāng)前的參數(shù),再通過調(diào)用setDampingRatio()方法設(shè)置要增加到彈簧上的阻尼比。

系統(tǒng)同時(shí)也定義了一些常用的dampingRatio。

DAMPING_RATIO_HIGH_BOUNCY效果:

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
high_bounce-min

DAMPING_RATIO_MEDIUM_BOUNCY效果:

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
medium_bounce-min

DAMPING_RATIO_LOW_BOUNCY效果:

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
low_bounce-min

DAMPING_RATIO_NO_BOUNCY效果:

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
no_bounce-min

相信大家通過GIF,就能很快明白其含義了。

 

剛度stiffness

剛度定義了用于衡量彈簧強(qiáng)度的彈簧常量。通過setStiffness()方法來設(shè)置剛度值,類似的,系統(tǒng)也定義了一些默認(rèn)的剛度常量。

STIFFNESS_HIGH效果:

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
high_stiffness-min

STIFFNESS_MEDIUM效果:

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
medium_stiffness-min

STIFFNESS_LOW效果:

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
low_stiffness-min

STIFFNESS_VERY_LOW效果:

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
very_low_stiffness-min
 

阻尼

物理動(dòng)畫的另一個(gè)常用場(chǎng)景,則是創(chuàng)建拉動(dòng)的阻尼效果,相比生硬的控制,通過阻尼設(shè)置拉動(dòng)效果,動(dòng)畫會(huì)更加符合物理定律,讓動(dòng)畫更加優(yōu)雅。不過,設(shè)置阻尼動(dòng)畫,其實(shí)并不需要Google的Spring Animation,我們通過一個(gè)函數(shù),即可完成阻尼效果的實(shí)現(xiàn),其實(shí),所謂的阻尼,即在拉動(dòng)過程中,將線性的拉動(dòng)距離,通過一個(gè)函數(shù)變換,轉(zhuǎn)換為非線性的遞減函數(shù),遞減函數(shù)的斜率,即為阻尼的力度,這樣的函數(shù)有很多,這里介紹其中一種。

阻尼效果

private fun doDamping(value: Float): Float {
    return if (value < 0)
        -sqrt((100f * abs(value)).toDouble()).toFloat()
    else
        sqrt((100f * value).toDouble()).toFloat()
}
 

通過這樣一個(gè)變換,就可以實(shí)現(xiàn)阻尼效果。

例如我們將第一個(gè)場(chǎng)景中的拉動(dòng)效果來增加阻尼效果,只需要在Move的過程中,不斷改變偏移量即可,代碼如下所示。

MotionEvent.ACTION_MOVE -> {
    test.translationX = doDamping(event.rawX - offsetX)
    test.translationY = doDamping(event.rawY - offsetY)
}
 

那么借助這樣一個(gè)函數(shù),就很方便的實(shí)現(xiàn)了變換效果,如圖所示。

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
zuni-min
 

其它

除了前面的示例外,這里還給大家提供了一些其它屬性的使用示例。

 

旋轉(zhuǎn)動(dòng)畫

設(shè)置ROTATION屬性,代碼如下所示。

test.setOnTouchListener { view, event ->
    val centerX = view.width / 2.0
    val centerY = view.height / 2.0
    val x = event.x
    val y = event.y

    fun updateRotation() {
        currentRotation = view.rotation + Math.toDegrees(atan2(x - centerX, centerY - y)).toFloat()
    }

    when (event.actionMasked) {
        MotionEvent.ACTION_DOWN -> updateRotation()
        MotionEvent.ACTION_MOVE -> {
            previousRotation = currentRotation
            updateRotation()
            val angle = currentRotation - previousRotation
            view.rotation += angle
        }
        MotionEvent.ACTION_UP -> SpringAnimation(
            test,
            DynamicAnimation.ROTATION
        ).animateToFinalPosition(0f)
    }
    true
}
 

效果如下所示。

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
rotate-min
 

縮放

設(shè)置SCALE_X和SCALE_Y屬性,代碼如下所示。

scaleGestureDetector = ScaleGestureDetector(this,
    object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            scaleFactor *= detector.scaleFactor
            test.scaleX *= scaleFactor
            test.scaleY *= scaleFactor
            return true
        }
    })
test.setOnTouchListener { _, event ->
    if (event.action == MotionEvent.ACTION_UP) {
        SpringAnimation(test, DynamicAnimation.SCALE_X).animateToFinalPosition(1f)
        SpringAnimation(test, DynamicAnimation.SCALE_Y).animateToFinalPosition(1f)
    } else {
        scaleGestureDetector.onTouchEvent(event)
    }
    true
}
 

效果如圖所示。

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
scale-min
 

位移

設(shè)置TRANSLATION_Y來實(shí)現(xiàn)View出現(xiàn)的動(dòng)畫效果,代碼如下所示。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    test.translationY = 1600f
    SpringAnimation(test, SpringAnimation.TRANSLATION_Y, 0f).apply {
        spring.stiffness = SpringForce.STIFFNESS_VERY_LOW
        spring.dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY
        setStartVelocity(-2000f)
        start()
    }
}
 

效果如下所示。

如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)  
up-min
 

KTX

在KTX中,Google還基于Spring Animation,提供了一些拓展函數(shù),來進(jìn)一步簡(jiǎn)化Spring的使用,地址如下所示。

implementation "androidx.dynamicanimation:dynamicanimation-ktx:1.0.0-alpha03"

“如何實(shí)現(xiàn)Material Component動(dòng)畫基礎(chǔ)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI