Cha*_*son 12 kotlin numberpicker android-number-picker android-jetpack android-jetpack-compose
在 Jetpack Compose 中创建 NumberPicker 小部件的推荐解决方案是什么?类似于下图。我可以在可组合项中使用 AndroidView 创建 NumberPicker,但该视图似乎不允许快速滑动或捕捉到位置。顺便说一句,下面的 UI 显示了连续放置的三个 NumberPicker。它不应该代表 DatePicker
nh7*_*nh7 20
我在 Jetpack Compose 中实现了 NumberPicker(不使用 AndroidView):https://gist.github.com/nhcodes/dc68c65ee586628fda5700911e44543f
选取器.kt
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun Picker(
items: List<String>,
state: PickerState = rememberPickerState(),
modifier: Modifier = Modifier,
startIndex: Int = 0,
visibleItemsCount: Int = 3,
textModifier: Modifier = Modifier,
textStyle: TextStyle = LocalTextStyle.current,
dividerColor: Color = LocalContentColor.current,
) {
val visibleItemsMiddle = visibleItemsCount / 2
val listScrollCount = Integer.MAX_VALUE
val listScrollMiddle = listScrollCount / 2
val listStartIndex = listScrollMiddle - listScrollMiddle % items.size - visibleItemsMiddle + startIndex
fun getItem(index: Int) = items[index % items.size]
val listState = rememberLazyListState(initialFirstVisibleItemIndex = listStartIndex)
val flingBehavior = rememberSnapFlingBehavior(lazyListState = listState)
val itemHeightPixels = remember { mutableStateOf(0) }
val itemHeightDp = pixelsToDp(itemHeightPixels.value)
val fadingEdgeGradient = remember {
Brush.verticalGradient(
0f to Color.Transparent,
0.5f to Color.Black,
1f to Color.Transparent
)
}
LaunchedEffect(listState) {
snapshotFlow { listState.firstVisibleItemIndex }
.map { index -> getItem(index + visibleItemsMiddle) }
.distinctUntilChanged()
.collect { item -> state.selectedItem = item }
}
Box(modifier = modifier) {
LazyColumn(
state = listState,
flingBehavior = flingBehavior,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.height(itemHeightDp * visibleItemsCount)
.fadingEdge(fadingEdgeGradient)
) {
items(listScrollCount) { index ->
Text(
text = getItem(index),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = textStyle,
modifier = Modifier
.onSizeChanged { size -> itemHeightPixels.value = size.height }
.then(textModifier)
)
}
}
Divider(
color = dividerColor,
modifier = Modifier.offset(y = itemHeightDp * visibleItemsMiddle)
)
Divider(
color = dividerColor,
modifier = Modifier.offset(y = itemHeightDp * (visibleItemsMiddle + 1))
)
}
}
private fun Modifier.fadingEdge(brush: Brush) = this
.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
.drawWithContent {
drawContent()
drawRect(brush = brush, blendMode = BlendMode.DstIn)
}
@Composable
private fun pixelsToDp(pixels: Int) = with(LocalDensity.current) { pixels.toDp() }
Run Code Online (Sandbox Code Playgroud)
PickerState.kt
@Composable
fun rememberPickerState() = remember { PickerState() }
class PickerState {
var selectedItem by mutableStateOf("")
}
Run Code Online (Sandbox Code Playgroud)
PickerExample.kt
@Composable
fun PickerExample() {
Surface(modifier = Modifier.fillMaxSize()) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize()
) {
val values = remember { (1..99).map { it.toString() } }
val valuesPickerState = rememberPickerState()
val units = remember { listOf("seconds", "minutes", "hours") }
val unitsPickerState = rememberPickerState()
Text(text = "Example Picker", modifier = Modifier.padding(top = 16.dp))
Row(modifier = Modifier.fillMaxWidth()) {
Picker(
state = valuesPickerState,
items = values,
visibleItemsCount = 3,
modifier = Modifier.weight(0.3f),
textModifier = Modifier.padding(8.dp),
textStyle = TextStyle(fontSize = 32.sp)
)
Picker(
state = unitsPickerState,
items = units,
visibleItemsCount = 3,
modifier = Modifier.weight(0.7f),
textModifier = Modifier.padding(8.dp),
textStyle = TextStyle(fontSize = 32.sp)
)
}
Text(
text = "Interval: ${valuesPickerState.selectedItem} ${unitsPickerState.selectedItem}",
modifier = Modifier.padding(vertical = 16.dp)
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
预览:
ngl*_*ber 13
巧合的是,我上周实现了一个类似的屏幕。我无法在这里分享整个代码,但基本上我所做的是:
DatePicker。<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/datePicker"
android:theme="@style/DatePickerStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="false"
android:datePickerMode="spinner" />
Run Code Online (Sandbox Code Playgroud)
@Composable
fun DatePicker(
onDateSelected: (Date) -> Unit
) {
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { context ->
val view = LayoutInflater.from(context).inflate(R.layout.date_picker, null)
val datePicker = view.findViewById<DatePicker>(R.id.datePicker)
val calendar = Calendar.getInstance() // show today by default
datePicker.init(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
) { _, year, monthOfYear, dayOfMonth ->
val date = Calendar.getInstance().apply {
set(year, monthOfYear, dayOfMonth)
}.time
onSelectedDateUpdate(date)
}
datePicker
}
)
}
Run Code Online (Sandbox Code Playgroud)
ModalBottomSheetLayout编辑我的答案...NumberPicker也使用工作...
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { context ->
NumberPicker(context).apply {
setOnValueChangedListener { numberPicker, i, i2 -> }
minValue = 0
maxValue = 50
}
}
)
Run Code Online (Sandbox Code Playgroud)
这是结果。
| 归档时间: |
|
| 查看次数: |
13252 次 |
| 最近记录: |