Android开发系列(八)Jetpack Compose之LazyColumn

    LazyColumn是一种垂直滚动的列容器,用于显示大量项目的列表。具有以下特点:

  1. 惰性加载:LazyColumn仅在需要时加载和绘制列表项,而不会一次性加载整个列表。这种惰性加载的机制可以提高性能,并且适用于非常大的列表。

  2. 无限滚动:LazyColumn支持无限滚动,可以动态加载更多的列表项。通过使用LazyColumn的onScroll事件和加载更多数据的逻辑,可以实现无限滚动的效果。

  3. 自动测量:LazyColumn会自动计算和测量列表项的大小,因此您不需要手动指定列表项的大小。这使得在不同的屏幕尺寸或设备方向下适应不同大小的列表项变得更加简单。

  4. 可变项高度:LazyColumn可以处理项目高度的变化,例如在项目中添加或删除元素时。它会自动调整滚动位置和列表项布局,以适应更改后的列表。

    下面通过一个实例说明LazyColumn的使用方法

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun LazyColumnSample1() {
    val items = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
    var height: Dp
    with(LocalDensity.current) {
        height = 300.toDp()
    }

    val state = rememberLazyListState()
    val scope = rememberCoroutineScope()
    LazyColumn(state = state) {
        stickyHeader {
            Text(
                "Header", modifier = Modifier
                    .fillMaxWidth()
                    .background(Color.White)
                    .padding(vertical = 10.dp)
                    .clickable {
                      //  scope.launch { state.animateScrollToItem(2) }
                    },fontSize = 22.sp
            )
        }
        items(items) {
            Text(
                text = "Column Item :$it", modifier = Modifier
                    .height(height),
                fontSize = 20.sp
            )
            Divider()
            DisposableEffect(Unit) {
                Log.d("LazyColumn", "effect:$it")
                onDispose {
                    Log.e("LazyColumn", "onDispose:$it")
                }
            }
        }
    }
}

    在LazyColumn中,stickyHeader 添加粘性头部,items添加条目,效果如下图所示。

通过打印日志,当item显示时打印effect,当item销毁时打印onDispose,打印日志情况如下。

   一开始只显示8个item,当往下滑动时,才会创建可见的item,同时销毁不可见的item,对于有大量数据的列表,不用一下子创建大量的对象,从而有效利用内存。

与LazyColumn类似的是LazyRow,它们的区别是方向不一样,前者是垂直方向,后者是横向。

LazyVerticalGrid

   默认情况下,LazyColumn每一行只有一个item,如果需要有多个item,可以使用LazyVertivalGrid,示例如下

    在LazyVertivalGrid中,通过columns控制列数,这里设置为2,表示2两列,多行多列就形成了一个表格。

 

示例代码已上传到github,链接如下

工程代码地址

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是实现拖动LazyColumn的item可改变位置的组件的Kotlin代码,你可以参考使用: ```kotlin import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch @Composable fun DraggableLazyColumn( items: List<Any>, modifier: Modifier = Modifier, dragEnabled: Boolean = true, itemContent: @Composable (Any) -> Unit ) { val listState = rememberLazyListState() val draggingItemIndex = remember { mutableStateOf(-1) } Box( modifier = modifier.fillMaxSize(), contentAlignment = Alignment.TopStart ) { LazyColumn( state = listState, contentDirection = LayoutDirection.Ltr ) { itemsIndexed(items) { index, item -> DraggableItem( itemIndex = index, modifier = modifier, dragEnabled = dragEnabled, draggingItemIndex = draggingItemIndex, onDragStart = { draggingItemIndex.value = index }, onDragEnd = { draggingItemIndex.value = -1 }, onNewPosition = { newPosition -> if (newPosition != index) { val newList = items.toMutableList() val item = newList.removeAt(index) newList.add(newPosition, item) items.clear() items.addAll(newList) } } ) { itemContent(item) } } } } } @Composable private fun DraggableItem( itemIndex: Int, modifier: Modifier, dragEnabled: Boolean, draggingItemIndex: androidx.compose.runtime.MutableState<Int>, onDragStart: () -> Unit, onDragEnd: () -> Unit, onNewPosition: (Int) -> Unit, content: @Composable () -> Unit ) { val offsetY = remember { mutableStateOf(0f) } val coroutineScope = rememberCoroutineScope() Box( modifier = modifier.pointerInput(Unit) { if (dragEnabled) { forEachGesture { awaitPointerEventScope { val originalIndex = itemIndex if (it.down) { onDragStart() } if (it.offsetChange().y != 0f && draggingItemIndex.value == originalIndex) { offsetY.value += it.offsetChange().y val currentPosition = offsetY.value / ITEM_HEIGHT_DP coroutineScope.launch { onNewPosition(currentPosition.toInt().coerceIn(0, Int.MAX_VALUE)) } } if (it.up) { onDragEnd() offsetY.value = 0f } } } } } ) { content() } } private const val ITEM_HEIGHT_DP = 50.dp ``` 在使用该组件时,需要将你的实际数据列表传入其中的`items`参数,并在`itemConent`中根据传入的数据绘制每一个item。同时,你可以自定义一些样式和形状等来符合你的实际需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值