V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yl20181003
V2EX  ›  Android

菜鸡问个 Android Jetpack Compose 的问题,如何实现 VerticalPager 嵌套一个可滚动的 Cloumn

  •  
  •   yl20181003 · 72 天前 · 2466 次点击
    这是一个创建于 72 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想要的效果如下:

    https://youtube.com/shorts/unI7ztB5EE4?si=dxGw2OFCGLy6dawp

    有尝试使用 NestedScrollConnection 但没解决问题,外层的 VerticalPager 想要到下一页或者上一页,必须滑动很长的距离,体验很不好。想来是自己太菜了,特来求助各位大佬。另外有个疑问,我看文档描述,onPreScroll 方法返回值便是父级容器将要消耗的滚动量,但我直接返回 Offset(0.0f, available.y) 按理说应该子容器 Column 不会滚动,而是作为父容器的 VerticalPager 去消耗滚动量,进入下一页。但实际情况却是两个容器都不会出现滚动效果。

    @OptIn(ExperimentalFoundationApi::class)
    @Composable
    fun NestedScrollExample(modifier: Modifier = Modifier) {
        val pageCount = 5
        val pagerState = rememberPagerState(pageCount = { pageCount })
        val scrollStates = List(pageCount) { rememberScrollState() }
    
        val nestedScrollConnection = remember {
            object : NestedScrollConnection {
                override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                    val delta = available.y
                    val page = pagerState.currentPage
                    val scrollState = scrollStates[page]
    
                    // only test the scroll down case
                    // If the user scrolls down, and the column item of the current page has not scrolled to the bottom, let the child consume the scroll.
                    if (delta < 0) {
                        return if (scrollState.canScrollForward) Offset.Zero else Offset(0.0f, delta)
                    }
    
                    return super.onPreScroll(available, source)
                }
            }
    
        }
    
    
        VerticalPager(
            state = pagerState,
            modifier = modifier
                .nestedScroll(nestedScrollConnection)
                .fillMaxSize(),
        ) { page ->
            Column(
                modifier = Modifier
                    .verticalScroll(scrollStates[page])
                    .fillMaxSize()
            ) {
                repeat(20) {
                    Text("Page $page item $it", modifier = Modifier.padding(16.dp))
                }
            }
        }
    }
    
    5 条回复    2024-09-09 09:01:26 +08:00
    murmurkerman
        1
    murmurkerman  
       71 天前
    啊,这个不是好的么
    murmurkerman
        2
    murmurkerman  
       71 天前
    这个是好的,加上 key 来保留滚动位置

    @Preview
    @OptIn(ExperimentalFoundationApi::class)
    @Composable
    fun VerticalPagerWithLazyColumn(
    modifier: Modifier = Modifier
    ) {
    val pagerState = rememberPagerState(
    pageCount = {
    5
    }
    )

    VerticalPager(
    state = pagerState,
    key = { it },
    modifier = modifier.fillMaxSize()
    ) { page ->
    Box {
    Column(
    modifier = Modifier
    .verticalScroll(rememberScrollState())
    .fillMaxSize()

    ) {
    for (i in 0..20) {
    Text(
    "Item $i on page $page",
    modifier = Modifier.padding(30.dp)
    )
    }
    }
    Text(
    "Page $page", modifier = Modifier
    .padding(16.dp)
    .align(Alignment.Center)
    )
    }
    }
    }
    yl20181003
        3
    yl20181003  
    OP
       71 天前
    @murmurkerman 多谢大佬,我开机去试试 😂
    mxalbert1996
        4
    mxalbert1996  
       71 天前 via Android   ❤️ 1
    为什么要用自定义的 NestedScrollConnection ? Compose 的默认的 nested scroll 应该就是视频里的效果。
    然后 onPreScroll 是返回**你**消耗的滚动量,不是说你返回一个数值 Compose 就自动帮你消耗了。你要自己消耗,比如通过 pagerState.dispatchRawDelta()。
    yl20181003
        5
    yl20181003  
    OP
       69 天前
    @mxalbert1996 #4 `然后 onPreScroll 是返回**你**消耗的滚动量,不是说你返回一个数值 Compose 就自动帮你消耗了` 多谢提醒,这个我一直以为是交给 Compose 去消耗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2776 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 09:30 · PVG 17:30 · LAX 01:30 · JFK 04:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.