首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >HorizontalPager与LazyColum在另一个LazyColum - Jetpack组合中

HorizontalPager与LazyColum在另一个LazyColum - Jetpack组合中
EN

Stack Overflow用户
提问于 2022-05-14 14:02:03
回答 1查看 3.4K关注 0票数 10

我想要一个类似的效果TikToks配置文件屏幕。顶部是ProfilPictureusername,下面是带有TabRow (PostsDraftsLikesFavorites)的stickyHeader,下面是带有4个屏幕的HorizontalPager (PostsDraftsLikesFavorites),每个屏幕都包含一个列表。

如果我在撰写中构建这个,我就会崩溃,因为我不能在彼此内部嵌套两个LazyColums

下面是我试图做的事情的一个简短版本:

代码语言:javascript
运行
复制
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()中可组合的是:

代码语言:javascript
运行
复制
@Composable
fun PostList(){
    LazyColumn() {
        items(50){ index ->
            Button(onClick = { /*TODO*/ },
                modifier = Modifier.fillMaxWidth()) {
                Text(text = "Button $index")
            }
        }
    }
}

这是我遇到的撞车事故:

代码语言:javascript
运行
复制
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,这会导致糟糕的用户体验,因为它允许用户滚动,即使列表是空的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-21 13:10:08

在这种情况下,在外部级别使用可滚动的Row而不是LazyColumn更容易。

这应该能达到你想要的目的:

代码语言:javascript
运行
复制
package com.fujigames.nestedscrolltest

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp
import com.fujigames.nestedscrolltest.ui.theme.NestedScrollTestTheme
import com.google.accompanist.flowlayout.FlowRow
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.pagerTabIndicatorOffset
import com.google.accompanist.pager.rememberPagerState
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalPagerApi::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NestedScrollTestTheme {
                BoxWithConstraints {
                    val screenHeight = maxHeight
                    val scrollState = rememberScrollState()
                    Column(
                        modifier = Modifier
                            .fillMaxSize()
                            .verticalScroll(state = scrollState)
                    ) {
                        Box(
                            modifier = Modifier
                                .height(200.dp)
                                .fillMaxWidth()
                                .background(Color.LightGray), contentAlignment = Alignment.Center
                        ) {
                            Text(text = "HEADER")
                        }

                        Column(modifier = Modifier.height(screenHeight)) {
                            val tabList = listOf("Tab1", "Tab2")
                            val pagerState = rememberPagerState(initialPage = 0)
                            val coroutineScope = rememberCoroutineScope()

                            TabRow(
                                modifier = Modifier.fillMaxWidth(),
                                backgroundColor = Color.White,
                                contentColor = Color.Black,
                                selectedTabIndex = pagerState.currentPage,
                                // Override the indicator, using the provided pagerTabIndicatorOffset modifier
                                indicator = { tabPositions ->
                                    TabRowDefaults.Indicator(
                                        Modifier.pagerTabIndicatorOffset(pagerState, tabPositions)
                                    )
                                }
                            ) {
                                tabList.forEachIndexed { index, title ->
                                    Tab(
                                        text = { Text(title) },
                                        selected = pagerState.currentPage == index,
                                        onClick = {
                                            coroutineScope.launch {
                                                pagerState.animateScrollToPage(index)
                                            }
                                        },
                                    )
                                }
                            }

                            HorizontalPager(
                                state = pagerState,
                                count = tabList.size,
                                modifier = Modifier
                                    .fillMaxHeight()
                                    .nestedScroll(remember {
                                        object : NestedScrollConnection {
                                            override fun onPreScroll(
                                                available: Offset,
                                                source: NestedScrollSource
                                            ): Offset {
                                                return if (available.y > 0) Offset.Zero else Offset(
                                                    x = 0f,
                                                    y = -scrollState.dispatchRawDelta(-available.y)
                                                )
                                            }
                                        }
                                    })
                            ) { page: Int ->
                                when (page) {
                                    0 -> ListLazyColumn(50)
                                    1 -> ListFlowRow(5)
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun ListLazyColumn(items: Int) {
    LazyColumn(modifier = Modifier.fillMaxSize()) {
        items(items) { index ->
            Button(
                onClick = { /*TODO*/ },
                modifier = Modifier.fillMaxWidth()
            ) {
                Text(text = "Button $index")
            }
        }
    }
}

@Composable
fun ListFlowRow(items: Int) {
    FlowRow(modifier = Modifier.fillMaxSize()) {
        repeat(items) { index ->
            Button(
                onClick = { /*TODO*/ },
                modifier = Modifier.fillMaxWidth()
            ) {
                Text(text = "Button $index")
            }
        }

    }
}
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72240936

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档