Создание фона раздела LazyList

У меня возникли проблемы с определением, связана ли моя проблема с отсутствующей функцией Jetpack Compose или я не могу найти, как это сделать.

Допустим, я хочу сделать эту страницу

Он должен быть прокручиваемым, потому что контент длинный.

Я также хотел бы использовать ленивый столбец для загрузки списка пользователей, показанного на изображении.

Проблема в том, что у вас не может быть LazyColumn внутри вертикально прокручиваемого макета, поэтому я подумал, что просто сделаю всю страницу LazyColumn. Теперь есть еще одна проблема: я хочу, чтобы вокруг списка пользователей была рамка с цветом фона и закругленными границами, как показано, но вы не можете поместить рамку вокруг LazyListScope.items(), и если вы загрузите список как один составной элемент, например элемент {UserList()}, тогда он просто превращается в столбец, теряя ленивую часть.

Как бы это сделать?

5 ответов

Я добился такого поведения с помощью небольшого взлома:

  1. Используйте карту для каждого предмета
  2. Первая карточка должна иметь форму RoundedCornerShape с радиусами topStart и topEnd.
  3. Первая карточка должна иметь форму RoundedCornerShape с радиусами bottomStart и bottomEnd.
  4. Все остальные карты имеют прямоугольную форму.
  5. (Особый случай: если есть только один элемент, используйте обычную 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())

}
Другие вопросы по тегам