前言
Jetpack Compose 中的列表组件相对于之前的View方式要简单很多。
列表
竖向列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Composable fun MyList(mList: List<String>){ LazyColumn { items(mList.size){ ListItem(mList[it]) } } }
@Composable fun ListItem(text: String) { Text(text = text) }
|
调用
1
| MyList(listOf("张三","李四","王五"))
|
注意
新版本的items方法参数变了。
遍历带索引
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Composable fun MyListColumn(mList: List<MyModel>, itemClick: (MyModel, Int) -> Unit) { LazyColumn { itemsIndexed(mList) { index, item -> MyListItem(index, item, itemClick) } } }
@Composable fun MyListItem(index: Int, item: MyModel, itemClick: (MyModel, Int) -> Unit) {
}
|
横向列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Composable fun MyList(mList: List<String>){ LazyRow { items(mList.size){ ListItem(mList[it]) } } }
@Composable fun ListItem(text: String) { Text(text = text) }
|
调用
1
| MyList(mutableListOf<String>("A", "B", "C"))
|
设置间距
1
| horizontalArrangement= Arrangement.spacedBy(10.dp)
|
项间距
LazyColumn
1
| LazyColumn(verticalArrangement = Arrangement.spacedBy(16.dp))
|
LazyRow
1
| LazyRow(horizontalArrangement = Arrangement.spacedBy(16.dp))
|
详细示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Composable fun MyList(mList: List<String>, modifier: Modifier) { LazyRow( modifier = modifier, horizontalArrangement = Arrangement.spacedBy(10.dp) ) { itemsIndexed(mList) { index, item -> ListItem(index, item) }
} }
@Composable fun ListItem(index: Number, text: String) { Button( modifier = Modifier .width(100.dp) .height(40.dp) .background(Color.Transparent), shape = CommonTheme.CornerM, onClick = { Log.i("TAG", "ListItem: $index") }) { Text( text = text, fontSize = 16.sp, color = Color.White ) } }
|
点击事件带索引
水平
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.xhkjedu.zxs_android.R import com.xhkjedu.zxs_android.componts.ImgLocalBg
data class TopMenu(var name: String, var selected: Boolean = false)
@Composable fun MainTopMenuList( mList: MutableList<TopMenu>, modifier: Modifier = Modifier.fillMaxSize(), itemClick: (item: TopMenu, index: Int) -> Unit ) { LazyRow(modifier = modifier) { itemsIndexed(mList) { index, item -> MainTopMenuItem(index, item, itemClick) }
} }
@Composable fun MainTopMenuItem(index: Int, item: TopMenu, itemClick: (item: TopMenu, index: Int) -> Unit) { Column( modifier = Modifier .fillMaxHeight() .padding(start = 16.dp, end = 16.dp) .clickable { itemClick(item, index) } ) { Box( modifier = Modifier .weight(1f) .align(Alignment.CenterHorizontally) ) { Text( item.name, color = Color.White, fontSize = if (item.selected) 23.sp else 19.sp, modifier = Modifier.align(Alignment.Center) ) } Box( modifier = Modifier .size(16.dp) .align(Alignment.CenterHorizontally) ) { if (item.selected) { ImgLocalBg(R.drawable.main_menu_bottom) } } } }
|
垂直
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @Composable fun MyTaskList(mList: List<String>, modifier: Modifier) { LazyColumn(modifier = modifier, verticalArrangement = Arrangement.spacedBy(8.dp)) { itemsIndexed(mList) { index, item -> MyTaskListItem(index, item) }
} }
@Composable fun MyTaskListItem(index: Number, text: String) { Box( modifier = Modifier .fillMaxWidth() .height(50.dp) .background( color = Color(0x660600BF), shape = CommonTheme.CornerXs ) .clip(CommonTheme.CornerXs) .clickable { Log.i("TAG", "ListItem: $index") } ) { Text( text = text, fontSize = 16.sp, color = Color.White ) } }
|
高度等分
有这种需求
我们的列表有固定的项数,我们想让项的高度相等,均分父列表,并且能自适应父列表。
但是LazyColumn没有直接均分的属性,weight也是不能用的,该怎样实现呢?
获取列表的高度减去所有的间距,在计算项的高度,传给Item。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| @Composable fun MyTaskList(mList: List<String>, modifier: Modifier) {
val containerHeight = remember { mutableStateOf(0.dp) } val density = LocalDensity.current Box(modifier = modifier) { LazyColumn( modifier = Modifier .fillMaxSize() .onSizeChanged { size -> containerHeight.value = with(density) { size.height.toDp() } }, verticalArrangement = Arrangement.spacedBy(12.dp), ) { val itemHeight = (containerHeight.value - 12.dp * (mList.size - 1)) / mList.size itemsIndexed(mList) { index, item -> MyTaskListItem(index, item, itemHeight) } } }
}
@Composable fun MyTaskListItem(index: Number, text: String, itemHeight: Dp) { Row( modifier = Modifier .fillMaxWidth() .height(itemHeight) .background( color = Color(0x660600BF), shape = CommonTheme.CornerXs ) .clip(CommonTheme.CornerXs) .clickable { Log.i("TAG", "ListItem: $index") }, verticalAlignment = Alignment.CenterVertically ) {
} }
|
Grid
竖向Grid
可以理解为竖向列表,只不过一行可以设置多列。
顺序如下
1 2 3
| [0][1][2][3] [4][5][6][7] [8][9][10][11]
|
基本示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Composable fun ToolGridList(mList: List<String>) { LazyVerticalGrid( modifier = Modifier.fillMaxSize(), columns = GridCells.Fixed(2), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp), ) { items(mList.size) { index -> ToolGridItem(text = mList[index]) } } }
@Composable fun ToolGridItem(text: String) { Card( modifier = Modifier .height(40.dp), ) { Text(text) } }
|
注意
竖向Grid布局中的子项,也就是上面的GridItem中的根组件的宽度是自动使用父的,设置宽度不会生效。
横竖屏不同列数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import android.content.res.Configuration import androidx.compose.ui.platform.LocalConfiguration
@Composable fun MyGridList(mList: List<String>) { val configuration = LocalConfiguration.current val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE val columnCount = if (isLandscape) 2 else 1 LazyVerticalGrid(columns = GridCells.Fixed(columnCount)) { items(mList.size) { index -> GridItem(text = mList[index]) } } }
@Composable fun GridItem(text: String) { Card( modifier = Modifier.padding(16.dp).height(30.dp), ) { Text(text) } }
|
自适应列数
这种方式好在,它能自适应进行布局。
假如页面的宽度是700dp,我们设置minSize = 300.dp,这样它会自动变成两列,每列350dp。
如果页面的宽度变成了500dp,那么就会变成一列,列的宽度也是500dp。
总之还是比较智能的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Composable fun AppListView(mList: List<AppModel>) { LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 300.dp), contentPadding = PaddingValues(10.dp), verticalArrangement = Arrangement.Top ) { items(mList.size,key = {item -> item }) { Box( modifier = Modifier .padding(10.dp) .fillMaxSize() ) { AppListItem(mList[it]) } } } }
|
设置间距
1 2 3 4 5 6 7 8 9
| LazyVerticalGrid( columns = GridCells.Fixed(2), verticalArrangement = Arrangement.spacedBy(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp) ) { items(photos) { item -> PhotoItem(item) } }
|
横向Grid
可以理解为横向列表,只不过一列可以设置多行。
基本示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Composable fun MyGridList(mList: List<String>) { LazyHorizontalGrid(rows = GridCells.Fixed(2)) { items(mList.size) { index -> GridItem(text = mList[index]) } } }
@Composable fun GridItem(text: String) { Card( modifier = Modifier.padding(16.dp).height(30.dp), ) { Text(text) } }
|
注意
竖向Grid布局中的子项,也就是上面的GridItem中的根组件的高度是自动使用父的,设置高度不会生效。
Grid间距
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Composable fun MyTaskList(mList: List<String>, modifier: Modifier) { LazyVerticalGrid( modifier = modifier, columns = GridCells.Fixed(1), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp), ) { itemsIndexed(mList) { index, item -> MyTaskListItem(index, item) } } }
|