布冯 發表於 2023-8-8 14:47:00

Android开发 Jetpack Compose LazyColumn 与 LazyRow、LazyVerticalGrid、LazyHorizontalGrid、LazyVerticalStaggeredGrid

<h1><span style="color: rgba(22, 145, 121, 1)">前言</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">  此篇博客讲解LazyColumn 与 LazyRow、LazyVerticalGrid、LazyHorizontalGrid、LazyHorizontalGrid、LazyVerticalStaggeredGrid,在compose里LazyColumn与LazyRow与是用来延迟加载数据的,它对标原来xml里的ListView与RecyclerView。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">而LazyVerticalGrid、LazyHorizontalGrid对标的是原来xml的GridView,LazyHorizontalGrid、LazyVerticalStaggeredGrid对标是原来的瀑布流列表。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">  此外此博客还会讲解滚动状态监听、下拉刷新、自定义下拉刷新与上拉加载、侧滑Item删除等等例子,这里只用LazyColumn来实现举例,与其他列表大差不差,希望都能举一反三。</span></p>
<h1><span style="color: rgba(22, 145, 121, 1)">LazyColumn 纵向列表</span></h1>
<p>效果图</p>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230807164131360-950867796.gif" alt="" height="730" width="414"></p>
<p id="1691397693477">代码</p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>@Composable
fun APage() {
    val listData = remember {
      //mutableStateListOf 这个很关键,需要动态新增数据一定需要使用mutableStateListOf
      mutableStateListOf(
            "苹果" to R.mipmap.ic_fruit_apple,
            "香蕉" to R.mipmap.ic_fruit_banana,
            "牛油果" to R.mipmap.ic_fruit_avocado,
            "蓝莓" to R.mipmap.ic_fruit_blueberry,
            "椰子" to R.mipmap.ic_fruit_coconut,
            "葡萄" to R.mipmap.ic_fruit_grape,
            "哈密瓜" to R.mipmap.ic_fruit_hami_melon,
            "猕猴桃" to R.mipmap.ic_fruit_kiwifruit,
            "柠檬" to R.mipmap.ic_fruit_lemon,
            "荔枝" to R.mipmap.ic_fruit_litchi,
            "芒果" to R.mipmap.ic_fruit_mango,
      )
    }
    Column {
      Button(modifier = Modifier.fillMaxWidth(), onClick = { listData.add("山竹" to R.mipmap.ic_fruit_mangosteen) }) {
            Text(text = "新增数据")
      }
      //LazyColumn
      LazyColumn(
            Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center
      ) {
            //这个items很关键,LazyColumn一定需要使用这个
            items(listData.size){
                Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(20.dp)) {
                  Image(painter = painterResource(id = listData.second), contentDescription = null, modifier = Modifier
                        .width(100.dp)
                        .height(100.dp))
                  Text(text = listData.first, fontSize = 25.sp, modifier = Modifier.padding(start = 80.dp))
                }
            }
      }
    }
}</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">LazyRow 横向列表</span></h1>
<p>效果图</p>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230807164536388-441672983.gif" alt="" height="730" width="414"></p>
<p>代码</p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>@Composable
fun APage() {
    val listData = remember {
      //mutableStateListOf 这个很关键,需要动态新增数据一定需要使用mutableStateListOf
      mutableStateListOf(
            "苹果" to R.mipmap.ic_fruit_apple,
            "香蕉" to R.mipmap.ic_fruit_banana,
            "牛油果" to R.mipmap.ic_fruit_avocado,
            "蓝莓" to R.mipmap.ic_fruit_blueberry,
            "椰子" to R.mipmap.ic_fruit_coconut,
            "葡萄" to R.mipmap.ic_fruit_grape,
            "哈密瓜" to R.mipmap.ic_fruit_hami_melon,
            "猕猴桃" to R.mipmap.ic_fruit_kiwifruit,
            "柠檬" to R.mipmap.ic_fruit_lemon,
            "荔枝" to R.mipmap.ic_fruit_litchi,
            "芒果" to R.mipmap.ic_fruit_mango,
      )
    }
    Column {
      Button(modifier = Modifier.fillMaxWidth(), onClick = { listData.add("山竹" to R.mipmap.ic_fruit_mangosteen) }) {
            Text(text = "新增数据")
      }
      //LazyRow
      LazyRow(
            Modifier.fillMaxSize(),
      ) {
            //这个items很关键
            items(listData.size){
                Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(20.dp)) {
                  Image(painter = painterResource(id = listData.second), contentDescription = null, modifier = Modifier
                        .width(100.dp)
                        .height(100.dp))
                  Text(text = listData.first, fontSize = 25.sp)
                }
            }
      }
    }
}</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">LazyVerticalGrid 纵向宫格列表</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">效果图</span></p>
<p><span style="color: rgba(22, 145, 121, 1)"><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230807172327662-937515525.gif" alt="" height="730" width="414"></span></p>
<p id="1691400209274">代码</p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>@Composable
fun APage() {
    val listData = remember {
      //mutableStateListOf 这个很关键,需要动态新增数据一定需要使用mutableStateListOf
      mutableStateListOf(
            "苹果" to R.mipmap.ic_fruit_apple,
            "香蕉" to R.mipmap.ic_fruit_banana,
            "牛油果" to R.mipmap.ic_fruit_avocado,
            "蓝莓" to R.mipmap.ic_fruit_blueberry,
            "椰子" to R.mipmap.ic_fruit_coconut,
            "葡萄" to R.mipmap.ic_fruit_grape,
            "哈密瓜" to R.mipmap.ic_fruit_hami_melon,
            "猕猴桃" to R.mipmap.ic_fruit_kiwifruit,
            "柠檬" to R.mipmap.ic_fruit_lemon,
            "荔枝" to R.mipmap.ic_fruit_litchi,
            "芒果" to R.mipmap.ic_fruit_mango,
            "橘子" to R.mipmap.ic_fruit_orange,
            "梨子" to R.mipmap.ic_fruit_pear,
      )
    }
    Column {
      Button(modifier = Modifier.fillMaxWidth(), onClick = { listData.add("山竹" to R.mipmap.ic_fruit_mangosteen) }) {
            Text(text = "新增数据")
      }
      //LazyVerticalGrid
      //columns 设置显示几列
      LazyVerticalGrid(columns = GridCells.Fixed(3)) {
            items(listData.size){
                Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(20.dp)) {
                  Image(painter = painterResource(id = listData.second), contentDescription = null, modifier = Modifier
                        .width(90.dp)
                        .height(90.dp))
                  Text(text = listData.first, fontSize = 18.sp)
                }
            }
      }
    }
}</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">LazyHorizontalGrid横向宫格列表</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">效果图</span></p>
<p><span style="color: rgba(22, 145, 121, 1)"><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230807171652462-1421989969.gif" alt="" height="730" width="414"></span></p>
<p id="1691399813900">代码</p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>@Composable
fun APage() {
    val listData = remember {
      //mutableStateListOf 这个很关键,需要动态新增数据一定需要使用mutableStateListOf
      mutableStateListOf(
            "苹果" to R.mipmap.ic_fruit_apple,
            "香蕉" to R.mipmap.ic_fruit_banana,
            "牛油果" to R.mipmap.ic_fruit_avocado,
            "蓝莓" to R.mipmap.ic_fruit_blueberry,
            "椰子" to R.mipmap.ic_fruit_coconut,
            "葡萄" to R.mipmap.ic_fruit_grape,
            "哈密瓜" to R.mipmap.ic_fruit_hami_melon,
            "猕猴桃" to R.mipmap.ic_fruit_kiwifruit,
            "柠檬" to R.mipmap.ic_fruit_lemon,
            "荔枝" to R.mipmap.ic_fruit_litchi,
            "芒果" to R.mipmap.ic_fruit_mango,
            "橘子" to R.mipmap.ic_fruit_orange,
            "梨子" to R.mipmap.ic_fruit_pear,
      )
    }
    Column {
      Button(modifier = Modifier.fillMaxWidth(), onClick = { listData.add("山竹" to R.mipmap.ic_fruit_mangosteen) }) {
            Text(text = "新增数据")
      }
      //LazyHorizontalGrid
      //rows 设置显示几行
      LazyHorizontalGrid(rows = GridCells.Fixed(4)) {
            items(listData.size){
                Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(20.dp)) {
                  Image(painter = painterResource(id = listData.second), contentDescription = null, modifier = Modifier
                        .width(90.dp)
                        .height(90.dp))
                  Text(text = listData.first, fontSize = 18.sp)
                }
            }
      }
    }
}</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)"><strong>LazyVerticalStaggeredGrid 纵向瀑布</strong></span><span style="color: rgba(22, 145, 121, 1)"><strong>流</strong></span><span style="color: rgba(22, 145, 121, 1)"><strong>列表</strong></span></h1>
<p><span style="color: rgba(186, 55, 42, 1)"><strong>请注意!LazyVerticalStaggeredGrid为实验性API,并且Compose版本需要1.4.0以上。 </strong><span style="color: rgba(0, 0, 0, 1)">这个其实跟我另一篇博客介绍的东西差不多 </span><span role="heading" aria-level="2">Android开发 Jetpack Compose FlowColumn与FlowRow瀑布流布局</span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)">效果图</span></p>
<p><span style="color: rgba(22, 145, 121, 1)"><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230808104909035-369094644.png"></span></p>
<p><span style="color: rgba(0, 0, 0, 1)">代码</span></p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>//因为LazyVerticalStaggeredGrid是实验性API,所以需要这个注解
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun APage() {
    val listData = remember {
      mutableStateListOf(
            "苹果" to R.mipmap.ic_fruit_apple,
            "香蕉" to R.mipmap.ic_fruit_banana,
            "牛油果" to R.mipmap.ic_fruit_avocado,
            "蓝莓" to R.mipmap.ic_fruit_blueberry,
            "椰子" to R.mipmap.ic_fruit_coconut,
            "葡萄" to R.mipmap.ic_fruit_grape,
            "哈密瓜" to R.mipmap.ic_fruit_hami_melon,
            "猕猴桃" to R.mipmap.ic_fruit_kiwifruit,
            "柠檬" to R.mipmap.ic_fruit_lemon,
            "荔枝" to R.mipmap.ic_fruit_litchi,
            "芒果" to R.mipmap.ic_fruit_mango,
      )
    }
    Column {
      //LazyVerticalStaggeredGrid
      //StaggeredGridCells设置显示几列
      LazyVerticalStaggeredGrid(columns = StaggeredGridCells.Fixed(4)) {
            items(listData.size){
                //这边设置一个item的随机高度,产生随机高度的瀑布效果
                val height = (80..200).random()
                Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(10.dp).background(
                  Color.Gray)) {
                  Image(painter = painterResource(id = listData.second), contentDescription = null, modifier = Modifier
                        .width(90.dp)
                        .height(height.dp))
                  Text(text = listData.first, fontSize = 18.sp)
                }
            }
      }
    }
}</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">LazyHorizontalStaggeredGrid 横向</span><span style="color: rgba(22, 145, 121, 1)"><strong>瀑布</strong></span><span style="color: rgba(22, 145, 121, 1)"><strong>流</strong></span><span style="color: rgba(22, 145, 121, 1)"><strong>列表</strong></span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">请注意!LazyHorizontalStaggeredGrid 为实验性API,并且Compose版本需要1.4.0以上。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">效果图</span></p>
<p><span style="color: rgba(22, 145, 121, 1)"><strong><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230808112018404-909522255.gif" alt="" height="726" width="410"></strong></span></p>
<p id="1691464820021">代码</p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>//因为LazyHorizontalStaggeredGrid是实验性API,所以需要这个注解
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun APage() {
    val listData = remember {
      mutableStateListOf(
            "苹果" to R.mipmap.ic_fruit_apple,
            "香蕉" to R.mipmap.ic_fruit_banana,
            "牛油果" to R.mipmap.ic_fruit_avocado,
            "蓝莓" to R.mipmap.ic_fruit_blueberry,
            "椰子" to R.mipmap.ic_fruit_coconut,
            "葡萄" to R.mipmap.ic_fruit_grape,
            "哈密瓜" to R.mipmap.ic_fruit_hami_melon,
            "猕猴桃" to R.mipmap.ic_fruit_kiwifruit,
            "柠檬" to R.mipmap.ic_fruit_lemon,
            "荔枝" to R.mipmap.ic_fruit_litchi,
            "芒果" to R.mipmap.ic_fruit_mango,
      )
    }
    Column {
      //LazyHorizontalStaggeredGrid
      //StaggeredGridCells设置显示几行
      LazyHorizontalStaggeredGrid(rows = StaggeredGridCells.Fixed(4)) {
            items(listData.size){
                //这边设置一个item的随机宽度,产生随机宽度的瀑布效果
                val width = (80..200).random()
                Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(10.dp).background(
                  Color.Gray)) {
                  Image(painter = painterResource(id = listData.second), contentDescription = null, modifier = Modifier
                        .width(width.dp)
                        .height(90.dp))
                  Text(text = listData.first, fontSize = 18.sp)
                }
            }
      }
    }
}</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">列表的滚动监听与设置滚动位置</span></h1>
<p>这里使用LazyColumn举例,因为其他形式的列表基本差不多。如果你不太了解下面代码中的rememberCoroutineScope,请参考博客 <span role="heading" aria-level="2">Android开发 Jetpack_Compose_6 附带效应</span>&nbsp; 这属于附带效应中的知识。 如果你疑问为什么要使用rememberCoroutineScope?这是因为onClick不属于协程域和compose域,而rememberLazyListState需要协程域内才能调用。</p>
<p>效果图</p>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230808144743586-254076033.gif" alt=""></p>
<p id="1691477266077"></p>
<p id="1691402221111">代码</p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>@Composable
fun APage() {
    val listData = remember {
      mutableStateListOf(
            "苹果" to R.mipmap.ic_fruit_apple,
            "香蕉" to R.mipmap.ic_fruit_banana,
            "牛油果" to R.mipmap.ic_fruit_avocado,
            "蓝莓" to R.mipmap.ic_fruit_blueberry,
            "椰子" to R.mipmap.ic_fruit_coconut,
            "葡萄" to R.mipmap.ic_fruit_grape,
            "哈密瓜" to R.mipmap.ic_fruit_hami_melon,
            "猕猴桃" to R.mipmap.ic_fruit_kiwifruit,
            "柠檬" to R.mipmap.ic_fruit_lemon,
            "荔枝" to R.mipmap.ic_fruit_litchi,
            "芒果" to R.mipmap.ic_fruit_mango,
      )
    }
    //协程范围
    val coroutineScope = rememberCoroutineScope()
    //关键代码!滚动状态监听
    val listState = rememberLazyListState()
    Column {
      DescribeText(text = "当前位置 = ${listState.firstVisibleItemIndex}")
      DescribeText(text = "滚动偏移量 = ${listState.firstVisibleItemScrollOffset}")
      DescribeText(text = "是否正在滚动 = ${listState.isScrollInProgress}")
      DescribeText(text = "可以向前滚动(是否可以向下滚) = ${listState.canScrollForward}")
      DescribeText(text = "可以向后滚动(是否可以向上滚) = ${listState.canScrollBackward}")
      Button(modifier = Modifier.fillMaxWidth(), onClick = {
            coroutineScope.launch {
                listState.scrollToItem(0)//关键代码!点击回到最上面
            }
      }) {
            Text(text = "回到最上面")
      }
      LazyColumn(
            state = listState,
            verticalArrangement = Arrangement.Center,
            modifier = Modifier.fillMaxSize(),
      ) {
            items(listData.size) {
                Row(
                  verticalAlignment = Alignment.CenterVertically,
                  modifier = Modifier.padding(20.dp)
                ) {
                  Image(
                        painter = painterResource(id = listData.second),
                        contentDescription = null,
                        modifier = Modifier
                            .width(100.dp)
                            .height(100.dp)
                  )
                  Text(
                        text = listData.first,
                        fontSize = 25.sp,
                        modifier = Modifier.padding(start = 80.dp)
                  )
                }
            }
      }
    }
}

@Composable
fun DescribeText(text:String) {
    Text(text = text, color = Color.Black, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth())
}</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">使用pullRefresh简单实现下拉刷新</span></h1>
<p><span style="color: rgba(22, 145, 121, 1)"><span style="color: rgba(0, 0, 0, 1)">这种方式实现需要compose版本为1.4.0,使用pullRefresh与PullRefreshIndicator的组合</span></span></p>
<p><span style="color: rgba(22, 145, 121, 1)"><span style="color: rgba(0, 0, 0, 1)">效果图</span></span></p>
<p><span style="color: rgba(22, 145, 121, 1)"><span style="color: rgba(0, 0, 0, 1)"><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230808161845820-1509269656.gif" alt="" height="726" width="410"></span></span></p>
<p><span style="color: rgba(22, 145, 121, 1)"><span style="color: rgba(0, 0, 0, 1)">代码</span></span></p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>@OptIn(ExperimentalMaterialApi::class)
@Composable
fun APage() {
    val listData = remember {
      mutableStateListOf(
            R.mipmap.ic_fruit_apple,
            R.mipmap.ic_fruit_banana,
            R.mipmap.ic_fruit_avocado,
            R.mipmap.ic_fruit_blueberry,
            R.mipmap.ic_fruit_coconut,
            R.mipmap.ic_fruit_grape,
            R.mipmap.ic_fruit_hami_melon,
            R.mipmap.ic_fruit_kiwifruit,
            R.mipmap.ic_fruit_lemon,
            R.mipmap.ic_fruit_litchi,
            R.mipmap.ic_fruit_mango,
      )
    }
    //是否正在刷新
    val isRefreshing = remember {
      mutableStateOf(false)
    }

    //refreshing为设置当前是否在刷新状态,如果设置为true则onRefresh不会触发
    val pullRefreshState =
      rememberPullRefreshState(refreshing = isRefreshing.value, onRefresh = {
            isRefreshing.value = true
            //这个回调里可以执行刷新数据的网络请求
      })

    Box(modifier = Modifier.pullRefresh(state = pullRefreshState, enabled = true)) {
      LazyColumn(
            Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center
      ) {
            items(listData.size) {
                Image(
                  painter = painterResource(id = listData),
                  contentDescription = null,
                  modifier = Modifier
                        .padding(top = 20.dp, bottom = 20.dp)
                        .fillMaxWidth()
                        .height(100.dp)
                )
            }
      }
      //请注意。这个PullRefreshIndicator并不是我自己实现的compose方法,这是最新1.4.0版本新增的下拉指示物
      //请注意,Modifier.align(Alignment.TopCenter)是上面Box的子属性
      PullRefreshIndicator(
            refreshing = isRefreshing.value,
            state = pullRefreshState,
            modifier = Modifier.align(Alignment.TopCenter)
      )
    }
}</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">使用pullRefresh实现下拉刷新与上拉加载</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(22, 145, 121, 1)"><span style="color: rgba(0, 0, 0, 1)">这种方式实现需要compose版本为1.4.0</span></span>,这个是较为自定义的实现方式,相对上面的比较复杂。</span></p>
<p>效果图</p>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230808150358114-1357738397.gif" alt="" height="726" width="410"></p>
<p id="1691478239511"></p>
<p>代码</p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>@OptIn(ExperimentalMaterialApi::class)
@Composable
fun APage() {
    val listData = remember {
      mutableStateListOf(
            "苹果" to R.mipmap.ic_fruit_apple,
            "香蕉" to R.mipmap.ic_fruit_banana,
            "牛油果" to R.mipmap.ic_fruit_avocado,
            "蓝莓" to R.mipmap.ic_fruit_blueberry,
            "椰子" to R.mipmap.ic_fruit_coconut,
            "葡萄" to R.mipmap.ic_fruit_grape,
            "哈密瓜" to R.mipmap.ic_fruit_hami_melon,
            "猕猴桃" to R.mipmap.ic_fruit_kiwifruit,
            "柠檬" to R.mipmap.ic_fruit_lemon,
            "荔枝" to R.mipmap.ic_fruit_litchi,
            "芒果" to R.mipmap.ic_fruit_mango,
      )
    }
    //是否显示下拉刷新
    val isShowDownPullRefresh = remember {
      mutableStateOf(false)
    }
    //是否显示上拉加载
    val isShowUpPullLoading = remember {
      mutableStateOf(false)
    }

    //滚动状态监听
    val listState = rememberLazyListState()

    Column(modifier = Modifier
            //请注意!这里的pullRefresh是关键
      .pullRefresh(onPull = { pullDelta -&gt;
            //拉动中
            if (pullDelta &gt; 0){
                //触发下拉刷新,在这里可以实现请求刷新数据的逻辑
                isShowDownPullRefresh.value = true
                return@pullRefresh pullDelta
            } else {
                if (!listState.canScrollForward){
                  //触发上拉加载,在这里可以实现请求更多数据的逻辑
                  isShowUpPullLoading.value = true
                }
                //这里一定需要返回0,否者会影响向下滑动
                return@pullRefresh 0F
            }
      }, onRelease = { flingVelocity -&gt;
            //松开释放,停止拉动
            isShowDownPullRefresh.value = false
            isShowUpPullLoading.value = false
            return@pullRefresh flingVelocity
      }, true)
    ) {
      LazyColumn(
            Modifier.fillMaxSize(),
            state = listState,
            verticalArrangement = Arrangement.Center
      ) {
            //这里listData.size + 2, 加2是为了增加头部的”下拉刷新“与尾部的”上拉加载“
            items(listData.size + 2) {
                if (it == 0){
                  if (isShowDownPullRefresh.value){
                        Text(
                            text = "下拉刷新",
                            fontSize = 25.sp,
                            textAlign = TextAlign.Center,
                            modifier = Modifier.fillMaxWidth()
                        )
                  }
                  return@items
                }
                if (it == listData.size + 1){
                  if (isShowUpPullLoading.value){
                        Text(
                            text = "上拉加载",
                            fontSize = 25.sp,
                            textAlign = TextAlign.Center,
                            modifier = Modifier.fillMaxWidth()
                        )
                  }
                  return@items
                }
                Row(
                  verticalAlignment = Alignment.CenterVertically,
                  modifier = Modifier.padding(20.dp)
                ) {
                  Image(
                        painter = painterResource(id = listData.second),
                        contentDescription = null,
                        modifier = Modifier
                            .width(100.dp)
                            .height(100.dp)
                  )
                  Text(
                        text = listData.first,
                        fontSize = 25.sp,
                        modifier = Modifier.padding(start = 80.dp)
                  )
                }
            }
      }
    }
}</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">使用SwipeToDismiss实现侧滑删除</span></h1>
<p>关键代码是SwipeToDismiss与rememberDismissState</p>
<p>效果图</p>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202308/1497956-20230808184038379-1732603980.gif" alt="" height="726" width="410"></p>
<p>代码</p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun APage() {
    val listData = remember {
      mutableStateListOf(
            R.mipmap.ic_fruit_apple,
            R.mipmap.ic_fruit_banana,
            R.mipmap.ic_fruit_avocado,
            R.mipmap.ic_fruit_blueberry,
            R.mipmap.ic_fruit_coconut,
            R.mipmap.ic_fruit_grape,
            R.mipmap.ic_fruit_hami_melon,
            R.mipmap.ic_fruit_kiwifruit,
            R.mipmap.ic_fruit_lemon,
            R.mipmap.ic_fruit_litchi,
            R.mipmap.ic_fruit_mango,
      )
    }

    val coroutineScope = rememberCoroutineScope()

    Box() {
      LazyColumn(
            Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center
      ) {
            items(listData.size) { position -&gt;
                //创建侧滑状态,请注意这里是在items里面创建的
                val dismissState = rememberDismissState()
                SwipeToDismiss(
                  state = dismissState,
                  //允许侧滑的方向
                  directions = setOf(DismissDirection.EndToStart),
                  dismissThresholds = {
                        //清除项目需要刷过的阈值,值越大需要拖动的距离就会越长
                        FixedThreshold(100.dp)
                  },
                  //background是侧滑后会显示出来的隐藏内容
                  background = {
                        //判断侧滑的方向
                        if (dismissState.isDismissed(DismissDirection.EndToStart)) {
                            Box(
                              modifier = Modifier
                                    .fillMaxSize()
                                    .background(Color.Gray)
                            ) {
                              //删除图标
                              Icon(
                                    imageVector = Icons.Default.Delete,
                                    contentDescription = null,
                                    modifier = Modifier
                                        .padding(end = 30.dp)
                                        .width(50.dp)
                                        .height(50.dp)
                                        .align(Alignment.CenterEnd)
                                        .clickable {
                                          coroutineScope.launch {
                                                dismissState.reset()
                                                //点击了删除,将这个数据删除掉
                                                listData.removeAt(position)
                                          }
                                        }
                              )
                              //恢复图标
                              Icon(
                                    imageVector = Icons.Default.SettingsBackupRestore,
                                    contentDescription = null,
                                    modifier = Modifier
                                        .padding(end = 100.dp)
                                        .width(50.dp)
                                        .height(50.dp)
                                        .align(Alignment.CenterEnd)
                                        .clickable {
                                          coroutineScope.launch {
                                                //将侧滑状态恢复
                                                dismissState.reset()
                                          }
                                        }
                              )
                            }
                        }
                  }) {
                  Image(
                        painter = painterResource(id = listData),
                        contentScale = ContentScale.Inside,
                        contentDescription = null,
                        modifier = Modifier
                            .fillMaxWidth()
                            .background(Color.White)
                            .height(120.dp)
                            //使用drawBehind画一个上面和下面的边线
                            .drawBehind {
                              drawLine(
                                    Color.Blue,
                                    Offset(0f, 0f),
                                    Offset(size.width, 0f),
                                    strokeWidth = 3f
                              )
                              drawLine(
                                    Color.Blue,
                                    Offset(0f, size.height),
                                    Offset(size.width, size.height),
                                    strokeWidth = 3f
                              )
                            }
                  )
                }

            }
      }
    }
}</code></pre>
<h1>&nbsp;</h1>
<p>&nbsp;</p>
<p><span style="color: rgba(22, 145, 121, 1)">end</span></p>

</div>
<div id="MySignature" role="contentinfo">
    <div style="text-align: center">
    <p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/17611791.html </p>
    <div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/17611791.html
頁: [1]
查看完整版本: Android开发 Jetpack Compose LazyColumn 与 LazyRow、LazyVerticalGrid、LazyHorizontalGrid、LazyVerticalStaggeredGrid