Jetpack 中的 Itemdecoration compose
Itemdecoration in Jetpack compose
我目前正在评估我们是否可以在这个阶段将相当复杂的 UI 迁移到 Jetpack Compose,我正在努力解决以下问题。
我有一个无限滚动的垂直列表,其中包含各种不同的概念组件。其中一些是 headers,然后可以是一些文本,一些水平滚动(无限)列表,然后是一些分组组件,它们也垂直堆叠但概念上属于一个组。
@Compose
fun MyComplexList() {
LazyColumn {
item {
// some header
}
item {
// some horizontal content
LazyRow {
item {}
}
}
item {
// some other header
}
items(x) {
// Some text for each item
}
}
}
正如人们所见,使用 compose 完成这件事相当简单,而且代码比编写这个复杂的 RecyclerView + Adapter 少得多......
有一个例外:背景渐变,跨越(分组)Some infinite list of things
组件。 (图像中的倾斜渐变)
过去 (:D) 我会在 RecyclerView
上使用 ItemDecoration
跨多个项目绘制内容,但我找不到与 Compose 中类似的内容。
有人知道如何使用 compose 实现这一目标吗?
选项之一:
替换:
items(x) {
// Some text for each item
}
与:
item {
Column(modifier = Modifier.border(...).background(...)) { //Shape, color etc...
x.forEach {
// Some text for each item
}
}
}
经过你的回答,我明白了...
@Composable
fun ListWithBg() {
val lazyListState = rememberLazyListState()
val itemsCount = 50
BoxWithConstraints(Modifier.fillMaxSize()) {
ListBg(lazyListState, itemsCount, maxHeight) // see below
LazyColumn(state = lazyListState, modifier = Modifier.fillMaxSize()) {
item {
Column(
Modifier
.fillMaxWidth()
.background(Color.White)
) {
Text(
text = "Some header",
style = MaterialTheme.typography.h5,
modifier = Modifier.padding(16.dp)
)
}
}
item {
Text(
text = "Some infinite list of things",
style = MaterialTheme.typography.h5,
modifier = Modifier.padding(16.dp)
)
}
items(itemsCount) {
Text(
text = "Item $it",
Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 6.dp)
.background(Color.LightGray)
.padding(8.dp)
)
}
}
}
}
要根据背景更改背景,您可以定义如下内容:
@Composable
fun ListBg(lazyListState: LazyListState, itemsCount: Int, maxHeight: Dp) {
val firstVisibleIndex = lazyListState.firstVisibleItemIndex
val totalVisibleItems = lazyListState.layoutInfo.visibleItemsInfo.size
val hasNoScroll = itemsCount <= totalVisibleItems
val totalHeight = if (hasNoScroll) maxHeight else maxHeight * 3
val scrollableBgHeight = if (hasNoScroll) maxHeight else totalHeight - maxHeight
val scrollStep = scrollableBgHeight / (itemsCount + 2 - totalVisibleItems)
val yOffset = if (hasNoScroll) 0.dp else -(scrollStep * firstVisibleIndex)
Box(
Modifier
.wrapContentHeight(unbounded = true, align = Alignment.Top)
.background(Color.Yellow)
.offset(y = yOffset)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(totalHeight)
.drawBehind {
drawRoundRect(
Brush.linearGradient(
0f to Color.Red,
0.6f to Color.DarkGray,
1.0f to Color.Green,
),
)
}
)
}
}
结果如下:
我目前正在评估我们是否可以在这个阶段将相当复杂的 UI 迁移到 Jetpack Compose,我正在努力解决以下问题。
我有一个无限滚动的垂直列表,其中包含各种不同的概念组件。其中一些是 headers,然后可以是一些文本,一些水平滚动(无限)列表,然后是一些分组组件,它们也垂直堆叠但概念上属于一个组。
@Compose
fun MyComplexList() {
LazyColumn {
item {
// some header
}
item {
// some horizontal content
LazyRow {
item {}
}
}
item {
// some other header
}
items(x) {
// Some text for each item
}
}
}
正如人们所见,使用 compose 完成这件事相当简单,而且代码比编写这个复杂的 RecyclerView + Adapter 少得多......
有一个例外:背景渐变,跨越(分组)Some infinite list of things
组件。 (图像中的倾斜渐变)
过去 (:D) 我会在 RecyclerView
上使用 ItemDecoration
跨多个项目绘制内容,但我找不到与 Compose 中类似的内容。
有人知道如何使用 compose 实现这一目标吗?
选项之一:
替换:
items(x) {
// Some text for each item
}
与:
item {
Column(modifier = Modifier.border(...).background(...)) { //Shape, color etc...
x.forEach {
// Some text for each item
}
}
}
经过你的回答,我明白了...
@Composable
fun ListWithBg() {
val lazyListState = rememberLazyListState()
val itemsCount = 50
BoxWithConstraints(Modifier.fillMaxSize()) {
ListBg(lazyListState, itemsCount, maxHeight) // see below
LazyColumn(state = lazyListState, modifier = Modifier.fillMaxSize()) {
item {
Column(
Modifier
.fillMaxWidth()
.background(Color.White)
) {
Text(
text = "Some header",
style = MaterialTheme.typography.h5,
modifier = Modifier.padding(16.dp)
)
}
}
item {
Text(
text = "Some infinite list of things",
style = MaterialTheme.typography.h5,
modifier = Modifier.padding(16.dp)
)
}
items(itemsCount) {
Text(
text = "Item $it",
Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 6.dp)
.background(Color.LightGray)
.padding(8.dp)
)
}
}
}
}
要根据背景更改背景,您可以定义如下内容:
@Composable
fun ListBg(lazyListState: LazyListState, itemsCount: Int, maxHeight: Dp) {
val firstVisibleIndex = lazyListState.firstVisibleItemIndex
val totalVisibleItems = lazyListState.layoutInfo.visibleItemsInfo.size
val hasNoScroll = itemsCount <= totalVisibleItems
val totalHeight = if (hasNoScroll) maxHeight else maxHeight * 3
val scrollableBgHeight = if (hasNoScroll) maxHeight else totalHeight - maxHeight
val scrollStep = scrollableBgHeight / (itemsCount + 2 - totalVisibleItems)
val yOffset = if (hasNoScroll) 0.dp else -(scrollStep * firstVisibleIndex)
Box(
Modifier
.wrapContentHeight(unbounded = true, align = Alignment.Top)
.background(Color.Yellow)
.offset(y = yOffset)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(totalHeight)
.drawBehind {
drawRoundRect(
Brush.linearGradient(
0f to Color.Red,
0.6f to Color.DarkGray,
1.0f to Color.Green,
),
)
}
)
}
}
结果如下: