Android?Compose?自定義滑動進度條的實現(xiàn)代碼
Android Compose 自定義滑動進度條

androidx.compose.material3 我用1.2.0版本的Slider非常好用,但是升級到1.3.2后滑軌后面多了個點,滑塊背景也移除不掉而且默認透明了我暫時沒有找到讓他不透明。所以自定義了一個先用著。
@Composable
fun CustomSlider(
state: CustomSliderState,
modifier: Modifier = Modifier,
trackHeight: Dp = 4.dp,
thumbSize: Dp = 24.dp,
trackColor: Color = Color.Gray,
progressColor: Color = Color.Blue,
thumbColor: Color = Color.White,
onValueChange: ((Float) -> Unit)? = null,
onValueChangeFinished: ((Float) -> Unit)? = null
) {
var sliderWidth by remember { mutableFloatStateOf(0f) }
Box(
modifier = modifier
.height(thumbSize + 16.dp) // 確保足夠高度容納滑塊
.pointerInput(Unit) {
awaitEachGesture {
val event = awaitPointerEvent(PointerEventPass.Initial)
if (event.changes.firstOrNull()?.changedToDown() == true) {
val down = awaitFirstDown(requireUnconsumed = true)
state.setPressed(true)
val newPosition = (event.changes.first().position.x / sliderWidth).coerceIn(0f, 1f)
val newValue = state.range.start + newPosition * (state.range.endInclusive - state.range.start)
state.updateValue(newValue)
onValueChange?.invoke(state.value)
var drag: PointerInputChange?
do {
drag = awaitTouchSlopOrCancellation(down.id) { change, _ ->
if (change.positionChange() != Offset.Zero) change.consume()
}
} while (drag != null && !drag.isConsumed)
if (drag != null) {
val dragResult = drag(drag.id) {
val newPosition = (it.position.x / sliderWidth).coerceIn(0f, 1f)
val newValue = state.range.start + newPosition * (state.range.endInclusive - state.range.start)
state.updateValue(newValue)
onValueChange?.invoke(state.value)
}
// 確保完成回調(diào)被觸發(fā)
if (!dragResult || drag.isConsumed) {
onValueChangeFinished?.invoke(state.value)
}
} else {
onValueChangeFinished?.invoke(state.value)
}
}
}
},
contentAlignment = Alignment.CenterStart
) {
// 繪制軌道(Track)
Canvas(
modifier = Modifier
.fillMaxWidth()
.clip(CircleShape)
.height(trackHeight)
.align(Alignment.CenterStart)
.onSizeChanged { size ->
sliderWidth = size.width.toFloat()
}
) {
// 背景軌道
drawRect(
color = trackColor,
size = Size(size.width.toFloat(), trackHeight.toPx())
)
// 進度軌道
drawRect(
color = progressColor,
size = Size(
width = (state.value - state.range.start) / (state.range.endInclusive - state.range.start) * size.width,
height = trackHeight.toPx()
)
)
}
// 滑塊(Thumb)根據(jù)你自己需求替換
Box(
modifier = Modifier
.offset {
IntOffset(
x = ((state.value - state.range.start) / (state.range.endInclusive - state.range.start) * sliderWidth - thumbSize.toPx()/2).toInt(),
y = 0
)
}
.shadow(4.dp, CircleShape)
.size(thumbSize)
.background(thumbColor, CircleShape)
)
}
}
class CustomSliderState(
initialValue: Float,
internal val range: ClosedFloatingPointRange<Float> = 0f..1f
) {
private val _value = mutableFloatStateOf(initialValue.coerceIn(range))
private val _isPressed = mutableStateOf(false) // 新增按下狀態(tài)
val value: Float
get() = _value.floatValue
val isPressed: Boolean // 暴露給外部
get() = _isPressed.value
fun updateValue(newValue: Float) {
_value.floatValue = newValue.coerceIn(range)
}
fun setPressed(pressed: Boolean) { // 更新按下狀態(tài)
_isPressed.value = pressed
}
}
@Composable
fun rememberCustomSliderState(
initialValue: Float = 0f,
range: ClosedFloatingPointRange<Float> = 0f..1f
): CustomSliderState {
return remember { CustomSliderState(initialValue, range) }
}使用
val sliderState = rememberCustomSliderState(
initialValue = 0.5f,
range = 0f..100f
)
CustomSlider(
state = sliderState,
modifier = Modifier.fillMaxWidth().padding(horizontal = 36.dp),
trackHeight = 12.dp,
thumbSize = 24.dp,
trackColor = Color.LightGray,
progressColor = Color(0xFF6200EE),
thumbColor = Color.White,
onValueChange = {
Log.e("onValueChange","float---$it")
},
onValueChangeFinished = {
Log.e("onValueChangeFinished","float---$it")
}
)補充:Compose筆記(十五)--進度條
這一節(jié)了解一下Compose中的進度條,有兩種類型的進度條可供使用,分別是線性進度條(LinearProgressIndicator)和圓形進度條(CircularProgressIndicator),每種進度條又可分為確定模式和不確定模式。
1. 不確定模式
在不確定模式下,進度條會持續(xù)滾動,用于表示操作正在進行,但無法確定具體的完成進度。
2. 確定模式
在確定模式下,需要傳入 progress 參數(shù),該參數(shù)的值范圍是 0 到 1,表示操作的完成進度。
栗子:
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun ProgressBarsExample() {
Column(
modifier = Modifier.padding(top = 40.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// 不確定線性進度條
IndeterminateLinearProgressBar()
// 確定線性進度條
DeterminateLinearProgressBar()
// 不確定圓形進度條
IndeterminateCircularProgressBar()
// 確定圓形進度條
DeterminateCircularProgressBar()
// 自定義進度條樣式
CircularProgressBarExample()
}
}
@Composable
fun IndeterminateLinearProgressBar() {
LinearProgressIndicator()
}
@Composable
fun DeterminateLinearProgressBar() {
var progress by remember { mutableStateOf(0.5f)}
LinearProgressIndicator(
progress = progress
)
}
@Composable
fun IndeterminateCircularProgressBar() {
CircularProgressIndicator()
}
@Composable
fun DeterminateCircularProgressBar() {
var progress by remember { mutableStateOf(0.7f)}
CircularProgressIndicator(
progress = progress
)
}import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun CircularProgressBarExample() {
var progress by remember { mutableStateOf(0.2f) }
Column(
modifier = Modifier.size(400.dp).padding(top = 20.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
CircularProgressBar(
progress = progress,
modifier = Modifier.size(150.dp),
indicatorStrokeWidth = 4.dp,
backgroundCircleColor = if(progress in 0.0..0.2) Color.Yellow
else if(progress>0.2 && progress<=0.5)
Color.Red
else if(progress>0.5 && progress<0.8)
Color.Blue
else Color.White,
fontSize = 12.sp
)
Button(
modifier = Modifier.padding(top = 20.dp),
onClick = {
progress = if (progress < 1f) progress + 0.1f else 0f
}
) {
Text(text = "進度測試")
}
}
}import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun CircularProgressBar(
progress: Float,
modifier: Modifier = Modifier,
backgroundIndicatorColor: Color = Color.LightGray,
indicatorColor: Color = Color.Blue,
indicatorStrokeWidth: Dp = 10.dp,
backgroundCircleColor: Color = Color.White,
textColor: Color = Color.Black,
fontSize: TextUnit = 20.sp
) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) {
Canvas(modifier = modifier) {
drawBackgroundCircle(backgroundCircleColor)
drawBackgroundIndicator(backgroundIndicatorColor, indicatorStrokeWidth)
drawProgressIndicator(progress, indicatorColor, indicatorStrokeWidth)
}
Text(
text = "${(progress * 100).toInt()}%",
color = textColor,
fontSize = fontSize,
fontWeight = FontWeight.Bold
)
}
}
private fun DrawScope.drawBackgroundCircle(color: Color) {
drawCircle(
color = color,
radius = size.minDimension / 2
)
}
private fun DrawScope.drawBackgroundIndicator(
color: Color,
strokeWidth: Dp
) {
drawArc(
color = color,
startAngle = -90f,
sweepAngle = 360f,
useCenter = false,
style = Stroke(
width = strokeWidth.toPx(),
cap = StrokeCap.Round
),
size = Size(size.width, size.height)
)
}
private fun DrawScope.drawProgressIndicator(
progress: Float,
color: Color,
strokeWidth: Dp
) {
drawArc(
color = color,
startAngle = -90f,
sweepAngle = 360f * progress,
useCenter = false,
style = Stroke(
width = strokeWidth.toPx(),
cap = StrokeCap.Round
),
size = Size(size.width, size.height)
)
}如圖:

到此這篇關(guān)于Android Compose 自定義滑動進度條的文章就介紹到這了,更多相關(guān)Android Compose滑動進度條內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實現(xiàn)動態(tài)添加數(shù)據(jù)與堆疊折線圖詳解流程
堆疊折線圖是折線圖的一種,堆積折線圖用于顯示每一數(shù)值所占大小隨時間或有序類別而變化的趨勢,可能顯示數(shù)據(jù)點以表示單個數(shù)據(jù)值,也可能不顯示這些數(shù)據(jù)點。堆疊折線圖中,類別數(shù)據(jù)沿水平軸均勻分布,所有值數(shù)據(jù)沿垂直軸均勻分布2021-10-10
Android View 完美實現(xiàn)EditText 在軟鍵盤上邊的示例
本篇文章主要介紹了Android View 完美實現(xiàn)EditText 在軟鍵盤上邊的示例,具有一定的參考價值,有興趣的可以了解一下2017-08-08
Android開發(fā) Activity和Fragment詳解
本文主要介紹Android開發(fā) Activity和Fragment,這里對Activity和Fragment的知識做了詳細講解,并附簡單代碼示例,有興趣的小伙伴可以參考下2016-08-08
Android 啟動模式FLAG_ACTIVITY_CLEAR_TOP案例詳解
這篇文章主要介紹了Android 啟動模式FLAG_ACTIVITY_CLEAR_TOP案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08

