Создание фона раздела LazyList
У меня возникли проблемы с определением, связана ли моя проблема с отсутствующей функцией Jetpack Compose или я не могу найти, как это сделать.
Допустим, я хочу сделать эту страницу
Он должен быть прокручиваемым, потому что контент длинный.
Я также хотел бы использовать ленивый столбец для загрузки списка пользователей, показанного на изображении.
Проблема в том, что у вас не может быть LazyColumn внутри вертикально прокручиваемого макета, поэтому я подумал, что просто сделаю всю страницу LazyColumn. Теперь есть еще одна проблема: я хочу, чтобы вокруг списка пользователей была рамка с цветом фона и закругленными границами, как показано, но вы не можете поместить рамку вокруг LazyListScope.items(), и если вы загрузите список как один составной элемент, например элемент {UserList()}, тогда он просто превращается в столбец, теряя ленивую часть.
Как бы это сделать?
5 ответов
Я добился такого поведения с помощью небольшого взлома:
- Используйте карту для каждого предмета
- Первая карточка должна иметь форму RoundedCornerShape с радиусами topStart и topEnd.
- Первая карточка должна иметь форму RoundedCornerShape с радиусами bottomStart и bottomEnd.
- Все остальные карты имеют прямоугольную форму.
- (Особый случай: если есть только один элемент, используйте обычную RoundedCornerShape)
private val topShape = RoundedCornerShape(topStart = 4.dp, topEnd = 4.dp)
private val bottomShape = RoundedCornerShape(bottomStart = 4.dp, bottomEnd = 4.dp)
@Composable
fun LazyColumnCategory(
itemCount: Int,
idx: Int,
content: @Composable (Shape) -> Unit,
) {
Column {
content(
if (itemCount == 1)
RoundedCornerShape(4.dp)
else if (idx == 0)
topShape
else if (idx == itemCount - 1)
bottomShape
else
RectangleShape
)
if (idx != itemCount - 1)
Divider()
}
}
Используйте это в своей LazyColumn следующим образом:
LazyColumn {
itemsIndexed(yourList) { idx, data ->
LazyColumnCategory(itemCount = yourList.size, idx = idx) { shape ->
Card(shape = shape) {
// your content here
}
}
}
}
Будьте осторожны, применяя отступы к вашим картам. Всегда определяйте отступ перед высотой, иначе будут пробелы. (см. документы )
Если вы хотите иметь фон для группы элементов, вы можете установить фон только для элементов этой группы.
Хитрость заключается в том, чтобы установить фон перед другими вашими модификаторами, чтобы он применялся до того, как элемент будет стилизован, например:
ListItem(modifier = Modifier
.background(GrayBackground)
.padding(horizontal = 20.dp)
)
Это предполагает, что вы знаете индексы конкретных предметов, которые хотите поместить в коробку.
val list = ... //Contains all the items
val lowerBound = ... // Start of User List
val upperBound = ...//"
LazyColumn{
list.forEachIndexed{index, item ->
if(lowerBound == index){
item{
Text(Modifier.clip(RoundedCornerShape(topStartPercent = 50, topEndPercent = 50)) //User
.background (color)
)
}
else if(upperBound == index){
Text(Modifier.clip(RoundedCornerShape(bottomStartPercent = 50, bottomEndPercent = 50)) //User
.background (color)
}
else if(lowerBound < index < upperBound){
Text(Modifier.background(color)
else{
//Regular List Items
}
}
}
}
Это только обходной путь. Это даст точный эффект, но на самом деле это не коробка.
Более чистым решением было бы фактически создать настраиваемый Composable и после обнаружения lowerBound добавить этот Composable как целый элемент, потому что, хотя вы не можете использовать элементы внутри поля, вы можете использовать наоборот.
Вот как:-
val list = ... //Contains all the items
val lowerBound = ... // Start of User List
val upperBound = ...//"
LazyColumn{
var x = 0
while(x++ != list.size()){
if(index == lowerBound){
item{
UserList(list.subList(lowerBound, upperBound))
}
}
else if(lowerBound < index < upperBound){
continue
}
else{
item{
User()
}
}
}
}
@Composable
fun UserList(list){
LazyColumn{
//Display List
}
}
Это делает колонку ленивой. Нет влияния на производительность
Если я правильно понял проблему, вам нужно отдельно определить макет «элемента», который вы представляете в своем LazyColumn. Допустим, в качестве примера у вас есть несколько лекций, которые вы хотите представить в своем списке. Вы можете определить это следующим образом:
LazyColumn(
//modifiers etc
) {
items(
items = **lectures** -> your list of items,
itemContent = {
**LectureListItem**(it) -> your specified layout
}
)
}
А под ним вы создаете свой составной
LectureListItem
который имеет нужный макет (если это поле, столбец, строка и все, что в нем). Пример:
@Composable
fun LectureListItem(
lecture: Lecture
) {
Box(
modifier = Modifier
.padding(8.dp)
.background(//exampleColor)
) {
//Other elements of your layout
}
}
По состоянию на 16.05.2022 лучший способ добавить фон в униформе к списку элементов — это использовать настраиваемый составной объект, который вкладывает *listOf<Any // ваш класс данных />() в LazyColumn() — «item { }" блок.
Ниже приведен пример функции, расширяющей область действия LazyColumn().
fun LazyListScope.itemGroup(list: List<Any>) {
return this.item {
//**Some composable you want to display*/
}
}
в блоке возврата вышеприведенной функции включите Column()
Column(
modifier = Modifier
.clip(RoundedCornerShape(5))
.background(DarkShade.copy(0.15f))
.padding(horizontal = padding.medium, vertical = padding.small),
verticalArrangement = Arrangement.spacedBy(padding.small)
) {
//**your list of items*/
}
Этот Column() позволяет вам стилизовать фон так, как вам хочется; цвет , обивка , форма и многое другое. Когда у вас есть предпочитаемый фон, вы можете создавать экземпляры элементов списка с помощью цикла for.
list.forEach { item ->
ListItem(
icon = item.icon,
title = item.title,
subtitle = item.subtitle,
onClick = item.onClick
)
}
Наконец, вы можете просто вызвать itemGroup() в любом LazyColumn() для использования
LazyColumn {
itemGroup(emptyList())
}