Mar*_*ram 14 android kotlin android-jetpack-compose android-jetpack-compose-list
如何计算 LazyRow 中所选项目的位置并将其用于使项目在屏幕上居中?这些物品将根据其内容而具有不同的尺寸。
如果我选择lazyListState.animateScrollToItem(index)
所选项目将位于 LazyRow 的左侧。
我目前拥有的代码:
@Composable
fun Test() {
Column {
TestRow(listOf("Angola", "Bahrain", "Afghanistan", "Denmark", "Egypt", "El Salvador", "Fiji", "Japan", "Kazakhstan", "Kuwait", "Laos", "Mongolia"))
TestRow(listOf("Angola", "Bahrain", "Afghanistan"))
}
}
@OptIn(ExperimentalSnapperApi::class)
@Composable
fun TestRow(items: List<String>) {
val selectedIndex = remember { mutableStateOf(0) }
val lazyListState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
LazyRow(
modifier = Modifier.fillMaxWidth(),
state = lazyListState,
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally),
contentPadding = PaddingValues(horizontal = 12.dp),
flingBehavior = rememberSnapperFlingBehavior(
lazyListState = lazyListState,
snapOffsetForItem = SnapOffsets.Start
)
) {
itemsIndexed(items) { index, item ->
TestItem(
content = item,
isSelected = index == selectedIndex.value,
onClick = {
selectedIndex.value = index
coroutineScope.launch {
lazyListState.animateScrollToItem(index)
}
}
)
}
}
}
@Composable
fun TestItem(
content: String,
isSelected: Boolean,
onClick: () -> Unit
) {
Button(
modifier = Modifier.height(40.dp),
colors = ButtonDefaults.buttonColors(
backgroundColor = if (isSelected) Color.Green else Color.Yellow,
contentColor = Color.Black
),
elevation = null,
shape = RoundedCornerShape(5.dp),
contentPadding = PaddingValues(0.dp),
onClick = onClick
) {
Text(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 10.dp),
text = (content).uppercase(),
)
}
}
Run Code Online (Sandbox Code Playgroud)
该代码horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally)
是为了确保当没有足够的项目用于滚动时,LazyRow 将所有项目居中。包含 3 项的示例:
我尝试过在类似问题上发布的各种建议,但没有找到解决方案。 jetpack-compose-lazylist-possible-to-zoom-the-center-item 如何在 jetpackcompose 上的惰性列中聚焦不可见的项目 /jetpack-compose-make-the-first-element-in -a-lazyrow-与中心对齐-o
我找到了一个适合我需求的解决方案,因为我不希望在看不到所选项目的情况下导航到它。
此解决方案无法将屏幕上不可见的项目居中。
coroutineScope.launch {
val itemInfo = lazyListState.layoutInfo.visibleItemsInfo.firstOrNull { it.index == index }
if (itemInfo != null) {
val center = lazyListState.layoutInfo.viewportEndOffset / 2
val childCenter = itemInfo.offset + itemInfo.size / 2
lazyListState.animateScrollBy((childCenter - center).toFloat())
} else {
lazyListState.animateScrollToItem(index)
}
}
Run Code Online (Sandbox Code Playgroud)
希望
小智 6
改进@Markram 的答案
您可以创建“LazyListState”的扩展:
fun LazyListState.animateScrollAndCentralizeItem(index: Int, scope: CoroutineScope) {
val itemInfo = this.layoutInfo.visibleItemsInfo.firstOrNull { it.index == index }
scope.launch {
if (itemInfo != null) {
val center = this@animateScrollAndCentralizeItem.layoutInfo.viewportEndOffset / 2
val childCenter = itemInfo.offset + itemInfo.size / 2
this@animateScrollAndCentralizeItem.animateScrollBy((childCenter - center).toFloat())
} else {
this@animateScrollAndCentralizeItem.animateScrollToItem(index)
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后直接在您的可组合项中使用它:
val coroutineScope = rememberCoroutineScope()
coroutineScope.launch {
listState.animateScrollAndCentralizeItem(index , this)
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4370 次 |
最近记录: |