我想要一个类似于TikToks个人资料屏幕的效果。上面是ProfilPicture
和username
,下面是stickyHeader
和TabRow
(Posts
、Drafts
、Likes
、Favorites
),以下为带4个屏幕的HorizontalPager
(Posts
、Drafts
、Likes
、Favorites
),这些屏幕中的每一个都包含一个列表。
如果我在Compose中构建这个,就会崩溃,因为我不能将两个LazyColums
嵌套在一起。
下面是我尝试做的事情的一个简短版本:
val tabList = listOf("Posts", "Drafts", "Likes", "Favorites")
val pagerState: PagerState = rememberPagerState(initialPage = 0)
val coroutineScope = rememberCoroutineScope()
LazyColumn(modifier = Modifier.fillMaxSize()) {
item {
Box(
modifier = Modifier
.fillMaxWidth()
.height(50.dp),
contentAlignment = Alignment.Center
) {
//Profile Header (Picture, Username, Followers, etc)
Text(text = "Profile Picture")
}
}
stickyHeader {
TabRow(
modifier = Modifier.fillMaxWidth(),
backgroundColor = Color.Black,
contentColor = Color.White,
selectedTabIndex = pagerState.currentPage,
indicator = { tabPositions ->
TabRowDefaults.Indicator(
Modifier.pagerTabIndicatorOffset(pagerState, tabPositions)
)
}
) {
// Add tabs for all of our pages
tabList.forEachIndexed { index, title ->
Tab(
text = { Text(title) },
selected = pagerState.currentPage == index,
onClick = {
coroutineScope.launch {
pagerState.animateScrollToPage(index)
}
},
)
}
}
}
item {
HorizontalPager(
state = pagerState,
count = tabList.size
) { page: Int ->
when (page) {
0 -> PostsList()
1 -> DraftsList()
2 -> LikesList()
else -> FavoritesList()
}
}
}
}
而在PostList()
的内部组成例如是:
@Composable
fun PostList(){
LazyColumn() {
items(50){ index ->
Button(onClick = { /*TODO*/ },
modifier = Modifier.fillMaxWidth()) {
Text(text = "Button $index")
}
}
}
}
这是我得到的崩溃:
Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed. One of the common reasons is nesting layouts like LazyColumn and Column(Modifier.verticalScroll()). If you want to add a header before the list of items please add a header as a separate item() before the main items() inside the LazyColumn scope. There are could be other reasons for this to happen: your ComposeView was added into a LinearLayout with some weight, you applied Modifier.wrapContentSize(unbounded = true) or wrote a custom layout. Please try to remove the source of infinite constraints in the hierarchy above the scrolling container.
**编辑:**给LazyColumn
一个固定的高度可以防止应用崩溃,但这不是一个令人满意的解决方案。当HorizontalPager
中的4个列表大小不同时,会出现奇怪和错误的行为,看起来不对劲。我尝试的另一件事是使用FlowRow
而不是LazyColumn
,这似乎也有效并修复了崩溃,但在这里我也得到了一个奇怪的行为,HorizontalPager
中的列表同时同步滚动,这不是我想要的。
HorizontalPager
是什么使这项任务如此困难,没有它根本不是一个问题。
下面是测试项目:https://github.com/DaFaack/TikTokScrollBehaviourCompose
这就是当我给予LazyColumn
一个2500.dp
的固定高度时的样子,只有这样大的高度才能提供所需的滚动行为。这里的缺点是,即使列表是空的,它也有2500的高度,这会导致糟糕的用户体验,因为它允许用户在列表是空的情况下滚动
2条答案
按热度按时间ndh0cuux1#
在这种情况下,在外层使用可滚动的
Row
而不是LazyColumn
更容易。这应该能达到你的目的:
eufgjt7s2#
使用Material3简单实现该行为
1.转到
build.gradle
并导入伴奏者寻呼机:1.使用
PagerState
、CoroutineScope
、ScrollBehavior
、TabRow
和HorizontalPager
创建分页器屏幕,您可以使用TopAppBarDefaults
提供的不同scrolBehaviors
或实现您自定义的ScrollBehavior
:1.为
HorizontalPager
创建选项卡:完整代码:
结果: