在Jetpack Composose中创建NumberPicker Widget的推荐解决方案是什么?类似于下面的图片。我能够在我的组合中使用AndroidView创建一个NumberPicker,但视图似乎不允许投掷或捕捉到位置。顺便说一句,下面的UI显示了三个NumberPickers放置在一行中。它不应该代表DatePicker
ff29svar1#
巧合的是,我上周实现了一个这样的屏幕。我不能在这里分享整个代码,但基本上我所做的是:1.使用DatePicker创建布局(res/layout/date_picker.xml)。
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" />
1.然后,在你的可组合函数中使用它。
@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 } ) }
1.最后,在ModalBottomSheetLayout中使用它编辑我的答案...使用NumberPicker也可以...
ModalBottomSheetLayout
NumberPicker
AndroidView( modifier = Modifier.fillMaxWidth(), factory = { context -> NumberPicker(context).apply { setOnValueChangedListener { numberPicker, i, i2 -> } minValue = 0 maxValue = 50 } } )
这就是结果。
tcbh2hod2#
我知道也许你不是在找这样的东西。但是由于compose中还没有这样的小部件,所以compose就是为了让你更容易地构建自己的组件。所以除了android.widget NumberPicker,你可以做这样的东西。您可以像更改NumberPicker小部件那样更改可视化,并添加回调和其他内容。你在github上看过这个吗?ComposeNumberPicker.Kt
7jmck4yq3#
我们在数字选取器小部件的合成项目中使用这个库。https://github.com/ChargeMap/Compose-NumberPicker
zhte4eai4#
我在Jetpack Compose中实现了一个NumberPicker(不使用AndroidView):https://gist.github.com/nhcodes/dc68c65ee586628fda5700911e44543fPicker.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() }
PickerState.kt
@Composable fun rememberPickerState() = remember { PickerState() } class PickerState { var selectedItem by mutableStateOf("") }
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) ) } } }
预览:
4条答案
按热度按时间ff29svar1#
巧合的是,我上周实现了一个这样的屏幕。我不能在这里分享整个代码,但基本上我所做的是:
1.使用
DatePicker
创建布局(res/layout/date_picker.xml)。1.然后,在你的可组合函数中使用它。
1.最后,在
ModalBottomSheetLayout
中使用它编辑我的答案...使用
NumberPicker
也可以...这就是结果。
tcbh2hod2#
我知道也许你不是在找这样的东西。但是由于compose中还没有这样的小部件,所以compose就是为了让你更容易地构建自己的组件。所以除了android.widget NumberPicker,你可以做这样的东西。您可以像更改NumberPicker小部件那样更改可视化,并添加回调和其他内容。
你在github上看过这个吗?ComposeNumberPicker.Kt
7jmck4yq3#
我们在数字选取器小部件的合成项目中使用这个库。https://github.com/ChargeMap/Compose-NumberPicker
zhte4eai4#
我在Jetpack Compose中实现了一个NumberPicker(不使用AndroidView):https://gist.github.com/nhcodes/dc68c65ee586628fda5700911e44543f
Picker.kt
PickerState.kt
PickerExample.kt
预览: