使用Compose制作抖音快手視頻進度條Loading動畫效果
引言
現(xiàn)在互聯(lián)網(wǎng)產(chǎn)品,感覺誰家的App不整點視頻功能,嚴格意義上都不能說是一個現(xiàn)代互聯(lián)網(wǎng)App了??,我們知道最火的是抖音、快手這類短視頻App,在刷視頻的同時,他們的App交互上面的一些特色能讓我們一直沉浸在刷視頻中;
比如,我們今天要聊的,短視頻翻頁流列表,視頻加載緩沖的時候,Loading的設計:
它設計:在視頻底部,進度條上面,當視頻緩沖加載等待的時候,它有一個波紋的擴散效果,
即不干擾用戶刷視頻的操作,也沒有很明顯的突兀效果
(比如:突兀的屏幕中間大圓圈Loading,就很突兀)
Loading效果
我們先來看一下“抖音、快手App”的視頻進度條Loading效果(GIF圖稍微失真了點)

快手短視頻首頁的視頻Loading
從視頻里面可以看出來在視頻底部,出現(xiàn)緩沖加載視頻的時候,會有一個:“從中間往2邊擴散”的效果。
GIF圖放慢了一點,方便大家觀看,實際研究過程,我一般是通過錄制完視頻,通過相冊的視頻編輯,去一幀一幀看,做了哪些動作,如下:

看完,我們發(fā)現(xiàn):
1、一開始是在屏幕中間的位置,大概是20dp左右的寬度開始顯示;
2、從中間擴散到屏幕邊緣之后,會執(zhí)行漸隱;
3、漸隱到透明,又開始從中間往2邊擴散;
BoxWithConstraints代碼
有了上面的前奏,我們就可以開始我們的編碼了,那么在開始編碼前,肯定需要知道寬度是多少,這里我們拿BoxWithConstraints來包我們的child composable, 我們可以看到BoxWithConstraints的代碼如下:
// 代碼來自:androidx.compose.foundation.layout
@Composable
@UiComposable
fun BoxWithConstraints(
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.TopStart,
propagateMinConstraints: Boolean = false,
content:
@Composable @UiComposable BoxWithConstraintsScope.() -> Unit
) {
val measurePolicy = rememberBoxMeasurePolicy(contentAlignment, propagateMinConstraints)
SubcomposeLayout(modifier) { constraints ->
val scope = BoxWithConstraintsScopeImpl(this, constraints)
val measurables = subcompose(Unit) { scope.content() }
with(measurePolicy) { measure(measurables, constraints) }
}
}
里面用到了SubcomposeLayout,來推遲內(nèi)容組合,我們可以在BoxWithConstraintsScope里面獲取到最大寬度maxWidth (單位dp)。
Loading線條,我們可以用DrawScope.drawLine來畫,擴散效果肯定需要有動畫來更新。
animateFloat獲取動畫更新值
我們使用 rememberInfiniteTransition() 執(zhí)行無限動畫,使用animateFloat來獲取動畫更新的值:
// 代碼來自:androidx.compose.animation.core
@Composable
fun InfiniteTransition.animateFloat(
initialValue: Float,
targetValue: Float,
animationSpec: InfiniteRepeatableSpec<Float>
): State<Float>
初始值(initialValue)可以定義成50F(讀者可自行修改),目標值(targetValue)定義多少合適呢?
通過慢鏡頭查看“抖音、快手”的效果,發(fā)現(xiàn)它擴散完,會“漸隱到透明”,然后再從intialValue處開始重新擴散。
targetValue定義成maxWidth不行,那么我們拉大這個數(shù)值,可以定義成大概1.8倍的maxWidth;
由于maxWidth獲取到的是dp單位的,我們需要轉換成px,下面我們統(tǒng)一叫:width
val width = with(LocalDensity.current) { maxWidth.toPx() }
線條動畫值
然后,我們的線條動畫值就變成下面這樣:
val lineProgressAnimValue by infiniteTransition.animateFloat(
initialValue = 100F,
targetValue = width * 1.8F,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = TIME_PERIOD,
easing = FastOutLinearInEasing
)
)
)
private const val TIME_PERIOD = 1100
執(zhí)行漸隱
線條擴散到屏幕邊緣的時候,需要執(zhí)行漸隱,得出下面的alpha
val lineAlphaValue = if(lineProgressAnimValue <= width) {
// 讀者可以根據(jù)自己體驗
lineProgressAnimValue * 1.0F/ width * 1.0F
// 讀者可以根據(jù)自己體驗
//Math.min((lineProgressAnimValue.value) * 1.0F / width * 1.0F, 0.7F)
// 抖音、快手看效果都是1F,根據(jù)自己體驗來設置吧
// 1F
} else {
// 擴散到屏幕邊緣的時候,開始觸發(fā):漸隱
(width * 1.8F - lineProgressAnimValue) / width * 0.8F
}
// 線條寬度
val lineWidth = if(lineProgressAnimValue <= width) {
lineProgressAnimValue / 2
} else {
width / 2
}
最后,我們通過Canvas來繪制這個線條
Canvas(modifier = modifier) {
drawLine(
color = Color.White.copy(alpha = lineAlphaValue),
start = Offset(x = size.width / 2 - lineWidth, y = 0F),
end = Offset(x = size.width / 2 + lineWidth, y = 0F),
strokeWidth = 2.5F
)
}
最終效果

以上就是使用Compose制作抖音快手視頻進度條Loading動畫效果的詳細內(nèi)容,更多關于Compose視頻進度條Loading的資料請關注腳本之家其它相關文章!
相關文章
Android?NotificationListenerService?通知服務原理解析
這篇文章主要為大家介紹了Android?NotificationListenerService?通知服務原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11
Android實現(xiàn)點擊AlertDialog上按鈕時不關閉對話框的方法
這篇文章主要介紹了Android實現(xiàn)點擊AlertDialog上按鈕時不關閉對話框的方法,涉及設置監(jiān)聽的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-02-02
Android基于wheelView實現(xiàn)自定義日期選擇器
這篇文章主要為大家詳細介紹了Android基于wheelView實現(xiàn)自定義日期選擇器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07
Android簡單實現(xiàn)動態(tài)權限獲取相機權限及存儲空間等多權限
這篇文章主要介紹了Android簡單實現(xiàn)動態(tài)權限獲取相機權限及存儲空間等多權限,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下2022-07-07

