如何在Jetpack Compose中实现数字选择器?含库集成及原生实现示例
Jetpack Compose 数字选择器实现方案
一、添加第三方库 Compose-NumberPicker
- 确保项目依赖仓库包含Maven Central,在
settings.gradle中配置:
dependencyResolutionManagement { repositories { // 保留原有仓库,新增以下行 mavenCentral() } }
- 在模块级
build.gradle.kts(或build.gradle)中添加依赖,将latest-version替换为仓库最新版本号:
dependencies { implementation "com.chargemap.compose:numberpicker:latest-version" }
- 基础使用示例:
var selectedNumber by remember { mutableStateOf(5) } BasicNumberPicker( value = selectedNumber, onValueChange = { selectedNumber = it }, range = 0..10, )
二、不依赖第三方库的原生实现
方案1:滚轮式数字选择器
基于LazyColumn实现滚动选中逻辑,支持范围限制与选中项高亮:
@Composable fun CustomWheelNumberPicker( minValue: Int, maxValue: Int, initialValue: Int, onValueChange: (Int) -> Unit ) { var selectedValue by remember { mutableStateOf(initialValue.coerceIn(minValue, maxValue)) } val listState = rememberLazyListState( initialFirstVisibleItemIndex = selectedValue - minValue ) // 滚动时同步选中值 LaunchedEffect(listState.firstVisibleItemIndex) { val newValue = minValue + listState.firstVisibleItemIndex if (newValue != selectedValue) { selectedValue = newValue onValueChange(newValue) } } Column( modifier = Modifier .width(100.dp) .height(150.dp) .clip(RoundedCornerShape(8.dp)) .border(1.dp, Color.Gray, RoundedCornerShape(8.dp)) .padding(vertical = 8.dp), horizontalAlignment = Alignment.CenterHorizontally ) { // 选中项边框指示器 Box( modifier = Modifier .fillMaxWidth() .height(50.dp) .border(top = 1.dp, bottom = 1.dp, color = Color.Blue) ) LazyColumn( state = listState, horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxSize() .layout { measurable, constraints -> val placeable = measurable.measure(constraints) layout(placeable.width, placeable.height) { // 让列表初始滚动到选中项居中位置 placeable.placeRelative(0, (placeable.height / 2) - (50.dp.roundToPx() / 2)) } } ) { items(maxValue - minValue + 1) { index -> val value = minValue + index Text( text = value.toString(), fontSize = if (value == selectedValue) 20.sp else 16.sp, fontWeight = if (value == selectedValue) FontWeight.Bold else FontWeight.Normal, color = if (value == selectedValue) Color.Blue else Color.Black, modifier = Modifier .padding(vertical = 16.dp) .width(80.dp) .height(50.dp) .wrapContentHeight() ) } } } } // 使用示例 @Composable fun WheelPickerDemo() { var selectedNumber by remember { mutableStateOf(5) } Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { CustomWheelNumberPicker( minValue = 0, maxValue = 10, initialValue = selectedNumber, onValueChange = { selectedNumber = it } ) Spacer(modifier = Modifier.height(20.dp)) Text(text = "选中值: $selectedNumber") } }
方案2:按钮控制式数字选择器
适合需要点击上下箭头调整数值的场景:
@Composable fun ButtonControlNumberPicker( minValue: Int, maxValue: Int, initialValue: Int, onValueChange: (Int) -> Unit ) { var selectedValue by remember { mutableStateOf(initialValue.coerceIn(minValue, maxValue)) } Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.SpaceBetween, modifier = Modifier .width(80.dp) .height(150.dp) .border(1.dp, Color.Gray, RoundedCornerShape(8.dp)) .padding(8.dp) ) { IconButton( onClick = { if (selectedValue < maxValue) { selectedValue++ onValueChange(selectedValue) } }, enabled = selectedValue < maxValue ) { Icon(Icons.Default.ArrowDropUp, contentDescription = "增加数值") } Text( text = selectedValue.toString(), fontSize = 24.sp, fontWeight = FontWeight.Bold ) IconButton( onClick = { if (selectedValue > minValue) { selectedValue-- onValueChange(selectedValue) } }, enabled = selectedValue > minValue ) { Icon(Icons.Default.ArrowDropDown, contentDescription = "减少数值") } } } // 使用示例 @Composable fun ButtonPickerDemo() { var selectedNumber by remember { mutableStateOf(3) } Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { ButtonControlNumberPicker( minValue = 0, maxValue = 10, initialValue = selectedNumber, onValueChange = { selectedNumber = it } ) Spacer(modifier = Modifier.height(20.dp)) Text(text = "当前选中: $selectedNumber") } }
内容的提问来源于stack exchange,提问作者NewPartizal
相关产品推荐
相关产品推荐

