Jetpack ComposeにはSeekBarがないので、必要な場合は今の所自分で作ることになります。で作りました。0.1.0-dev04
での実装なので将来そのままでは動かなくなると思うのでご注意ください。
使う
実際の動作はこんな感じになります
実装
Draggableを使って実装します。横棒とか丸は頑張って描画してます。 Draggableは値の範囲がfixedなので、横幅が動的(いわゆるmatch_parent)の場合利用が難しいです。そのためDraw関数とparentSizeを使って、widthをstateに持つみたいなことをやってます。
@Composable private fun paint(): Paint { return Paint().apply { color = MaterialTheme.colors().primary isAntiAlias = true } } @Composable fun SeekBar( @FloatRange(from = 0.0, to = 1.0) progress: Float, fixedWidth: Dp? = null, onChangeProgress: (Float) -> Unit ) { val squareSize = 32.dp val barHeight = 8.dp val fixedWidthPx = withDensity(ambientDensity()) { fixedWidth?.toPx()?.value } val (width, setWidth) = state { fixedWidthPx ?: 0f } if (width == 0f) { Container( modifier = LayoutWidth.Fill ) { Draw { _, parentSize -> val newWidth = parentSize.width.value if (newWidth != width) { setWidth(newWidth) } } } } else { val squareSizePx = withDensity(ambientDensity()) { squareSize.toPx().value } val max = width - squareSizePx val min = 0.dp val (minPx, maxPx) = withDensity(ambientDensity()) { min.toPx().value to max } val position = animatedDragValue(maxPx * progress, minPx, maxPx) val paint = paint() Draggable( dragDirection = DragDirection.Horizontal, dragValue = position, onDragValueChangeRequested = { position.animatedFloat.snapTo(it) onChangeProgress(position.value / max) } ) { Container( modifier = fixedWidth?.let { LayoutWidth(it) } ?: LayoutWidth.Fill, alignment = Alignment.CenterLeft, height = squareSize ) { Stack { Padding( top = squareSize / 2 - barHeight / 2, left = squareSize / 2, right = squareSize / 2 ) { ColoredRect( Color.LightGray, height = barHeight ) } Draw { canvas, _ -> canvas.drawCircle( Offset(position.value + squareSizePx / 2, squareSizePx / 2), squareSizePx / 2, paint ) } } } } } }
おわりに
ProgressBarなども横幅fixedなんでスクラッチしたり、わりとスクラッチが必要だけど、結構カスタムなコンポーネント作るのそんなに難しくないので、UIライブラリがどんどん出てくるかもなと思ったりします。β、RCが待ち遠しいですね。