Layout and Styling
Within Litho, lists are implemented using the Lazy Collection API.
Layoutsβ
Lazy Collections are available as follows:
- LazyList - arranged as a sequential list.
- LazyGrid - arranged as a grid with the number of columns specified by the
columns
parameter. - LazyStaggeredGrid - arranged into columns where children are inserted into the first column that has space.
Horizontal listsβ
To make a Lazy Collection horizontal, set the parameter orientation = RecyclerView.HORIZONTAL
. By default, it's necessary to specify a height, such as style = Style.height(100.dp)
, as follows:
class HScrollFixedHeight : KComponent() {
override fun ComponentScope.render(): Component =
LazyList(
orientation = RecyclerView.HORIZONTAL,
style = Style.height(100.dp),
) { /* Add children */
}
}
Defining height behaviorβ
The height behavior of a horizontal list is determined by the crossAxisWrapMode
parameter.
Possible values are:
NoWrap
(default) - by default, a horizontal list requires a height to provided via thestyle
parameter, either as an explicit height (Style.height()) or as layout constraints (such as Style.flex()).MatchFirstChild
- the horizontal scroll height will be tied to the height of the first child.Dynamic
- the horizontal scroll height will match the tallest item in the list.
CrossAxisWrapMode.Dynamic
requires measuring all the components in the list. This is inefficient and should be avoided if possible.
Spacingβ
To add spacing around and between items, use LinearSpacing
. This will create an ItemDecorator
that will be applied to the underlying RecyclerView
. It automatically takes care of edge cases including equality checks (to avoid unnecessary layouts), orientation, and layout direction handling:
class LinearSpacingExample : KComponent() {
override fun ComponentScope.render(): Component =
LazyList(
itemDecoration = LinearSpacing(start = 10.dp, between = 5.dp),
) { /* Add children */
}
}
Sticky headersβ
To make a child 'sticky', specify the parameter isSticky = true
. This will cause the child to stick to the top of the Lazy Collection rather than being scrolled out of the viewport.
class StickyHeader(val names: List<String>) : KComponent() {
override fun ComponentScope.render(): Component {
val namesGroupedByFirstLetter = names.groupBy { it.first() }
return LazyList {
namesGroupedByFirstLetter.forEach { (firstLetter, names) ->
child(id = firstLetter, isSticky = true, component = Text("$firstLetter"))
children(items = names, id = { it }) { Text(it) }
}
}
}
}