Compose-时间选择器

本文介绍了一个基于Jetpack Compose的时间选择器实现方案,包括ColumnPicker和DatePicker组件的封装及使用方法。通过自定义滚动选择器,实现了日期选择功能,并探讨了优化方向。


前言

Compose 时间选择器;
核心滚轮部分借鉴了 Number Picker 经过博主修改封装;

这个组件目前还存在一定问题:
1.Compose 重组的优化 还没做到最好;
2.手势, 动画, 滚轮核心思路等 都借鉴 Number Picker, 是不是还能优化一些.

效果如图:
在这里插入图片描述


一、ColumnPicker

ColumnPicker 就不详解了, 感兴趣的自己看吧!

// ColumnPicker.kt
import androidx.compose.animation.core.*
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.layout.*
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.MaterialTheme
import androidx.compose.material.ProvideTextStyle
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
import kotlin.math.abs
import kotlin.math.roundToInt

/**
 * 条目高度.
 */
private val itemHeight = 38.dp

/**
 * 透明度控制, 每条目距离 差距
 */
private const val itemAlphaGap = 0.3f

/**
 * 条目数量. 这个暂时不能随便改.  目前得同时改逻辑才行;
 */
private const val columnCount = 5

/**
 * 数字滚轮 Picker
 */
@Composable
fun ColumnPicker(
  modifier: Modifier = Modifier,
  label: (Int) -> String = {
   
   
    it.toString()
  },
  value: Int,
  onValueChange: (Int) -> Unit,
  range: Iterable<Int>,
  textStyle: TextStyle = LocalTextStyle.current,
) {
   
   
  ListItemPicker(
    modifier = modifier,
    label = label,
    value = value,
    onValueChange = onValueChange,
    list = range.toList(),
    textStyle = textStyle
  )
}


@Composable
fun <T> ListItemPicker(
  modifier: Modifier = Modifier,
  label: (T) -> String = {
   
    it.toString() },
  value: T,
  onValueChange: (T) -> Unit,
  list: List<T>,
  textStyle: TextStyle = LocalTextStyle.current,
) {
   
   
  val columnHeightPx = with(LocalDensity.current) {
   
    itemHeight.toPx() }

  val coroutineScope = rememberCoroutineScope()

  val animatedOffset = remember {
   
    Animatable(0f) }
    .apply {
   
   
      val index = list.indexOf(value)
      val offsetRange = remember(value, list) {
   
   
        -((list.count() - 1) - index) * columnHeightPx to
                index * columnHeightPx
      }
      updateBounds(offsetRange.first, offsetRange.second)
    }
  val coercedAnimatedOffset = animatedOffset.value % columnHeightPx
  val currentIndex = getItemIndexForOffset(list, value, animatedOffset.value, columnHeightPx)

  Layout(
    modifier = modifier
      .draggable(
        orientation = Orientation.Vertical,
        state = rememberDraggableState {
   
    deltaY ->
          coroutineScope.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值