kotlin,数字滚动选择

发布于:2025-04-07 ⋅ 阅读:(38) ⋅ 点赞:(0)

用国内的通义灵码和codegeex都没有弄出来,最后只得用墙外的chatgpt才弄出一个满意的。kotlin真的有点难,好在有AI,让学习没这难了。

package com.example.mynumset

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.mynumset.ui.theme.MyNumSetTheme
import kotlinx.coroutines.launch
import androidx.compose.ui.graphics.Color

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            MyNumSetTheme {
                NumberPickerDemo()
            }
        }
    }
}

@Composable
fun NumberPicker(
    modifier: Modifier = Modifier,
    initialValue: Int = 0,
    range: IntRange = 0..100,
    onValueChange: (Int) -> Unit
) {
    val itemHeight = 50.dp
    val listState = rememberLazyListState(initialFirstVisibleItemIndex = initialValue)
    val coroutineScope = rememberCoroutineScope()
    val itemHeightPx = with(LocalDensity.current) { itemHeight.toPx() }

    // 实时计算当前选中项索引
    val selectedIndex by remember {
        derivedStateOf {
            val offset = listState.firstVisibleItemScrollOffset
            val index = listState.firstVisibleItemIndex
            if (offset > itemHeightPx / 2) index + 1 else index
        }
    }

    // 当滚动停止时,吸附到中间项并回调
    LaunchedEffect(listState.isScrollInProgress) {
        if (!listState.isScrollInProgress) {
            coroutineScope.launch {
                listState.animateScrollToItem(selectedIndex)
            }
            onValueChange(range.first + selectedIndex)
        }
    }

    LazyColumn(
        state = listState,
        modifier = modifier
            .height(itemHeight * 3)
            .width(100.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        contentPadding = PaddingValues(vertical = itemHeight),
        flingBehavior = rememberSnapFlingBehavior(lazyListState = listState)
    ) {
        items(range.count()) { index ->
            val value = range.first + index
            val isSelected = selectedIndex == index

            Text(
                text = value.toString(),
                fontSize = if (isSelected) 32.sp else 20.sp,
                fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal,
                color = if (isSelected) Color.Black else Color.Gray,
                modifier = Modifier
                    .height(itemHeight)
                    .fillMaxWidth(),
                textAlign = TextAlign.Center
            )
        }
    }
}

@Composable
fun NumberPickerDemo() {
    var selectedNumber by remember { mutableStateOf(50) }

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        NumberPicker(
            initialValue = selectedNumber,
            onValueChange = { selectedNumber = it }
        )

        Spacer(modifier = Modifier.height(16.dp))

        Text("当前选择: $selectedNumber", fontSize = 24.sp)
    }
}