jetpack compose NestedScrollConnection

夏季儿看看:
嵌套滑动(NestedScroll) | 你好 Compose
章节中的nestscroll

示例:伸缩 ToolBar

样例的代码地址:Compose 伸缩 ToolBar 的实现 | 你好 Compose

看到效果我想实现,滚动的时候,向上滚动,先折叠图片。向下滚动,先滚动列表,以保持最大的可视数据窗口

package com.example.myapplication.ui.nestscrolltest

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.max
import com.example.myapplication.R

/**
 *
 *      ╭︿︿︿╮
 *    {/ .  . /}
 *     ( (oo) )
 *      ︶︶︶
 *    Create by cps 2025/6/24  15:13
 *
 */

@Composable
fun ScrollBarView() {
    Surface(modifier = Modifier.fillMaxWidth(), color = Color.Gray) {
        val toolbarHeight = 200.dp
        var total = 0f
        val maxUpPx = with(LocalDensity.current) {
            total = toolbarHeight.roundToPx().toFloat()
            toolbarHeight.roundToPx().toFloat() - 56.dp.roundToPx().toFloat()
        }
        val minUpPx = 0f
        val toolbarOffsetHeightPx = remember {
            mutableFloatStateOf(0f)
        }
        val lazyListstate = rememberLazyListState(0, 0)

        val totalOffset by remember {
            derivedStateOf {
                var offset = 0
                for (i in 0 until lazyListstate.firstVisibleItemIndex) {
                    offset += lazyListstate.layoutInfo.visibleItemsInfo.firstOrNull { it.index == i }?.size
                        ?: 0
                }
                offset + lazyListstate.firstVisibleItemScrollOffset
                offset
            }
        }

        /**
         * 实现原理是: colume list 是一直滚动的
         *   唯一的区别是 ttilebar 的offset 什么时候需要执行
         */
        val nestedScrollConnect = remember {
            object : NestedScrollConnection {
                override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                    val delta = available.y
                    println("$totalOffset  ${toolbarOffsetHeightPx.floatValue}   $total")
                    if (delta > 0) {
                        if (totalOffset + toolbarOffsetHeightPx.floatValue.toInt() < 0) { //list的滚动偏移量跟目前的offset 一样了,需要减小offset 了
                            val newOffset = toolbarOffsetHeightPx.floatValue + delta
                            toolbarOffsetHeightPx.floatValue = newOffset.coerceIn(-maxUpPx, minUpPx)
                        }
                        return Offset.Zero
                    }
                    val newOffset = toolbarOffsetHeightPx.floatValue + delta
                    toolbarOffsetHeightPx.floatValue = newOffset.coerceIn(-maxUpPx, minUpPx)
                    return Offset.Zero
                }
//不需要
//                override fun onPostScroll(
//                    consumed: Offset,
//                    available: Offset,
//                    source: NestedScrollSource
//                ): Offset {
//                    if (totalOffset + toolbarOffsetHeightPx.floatValue.toInt() < 0) {
//                        return Offset.Zero
//                    } else {
//                        return available
//                    }
//                }
            }
        }

        Box(
            Modifier
                .fillMaxSize()
                .nestedScroll(nestedScrollConnect)
        ) {
            LazyColumn(
                contentPadding = PaddingValues(top = toolbarHeight),
                state = lazyListstate
            ) {
                items(100) {
                    Text(
                        "$it --------", Modifier
                            .fillMaxWidth()
                            .padding(16.dp)
                            .clickable {
                                println("it$it clicked")
                            }
                    )
                }
            }

        }
        ScrollableAppBar(
            title = "测试滚动",
            bgImageId = R.drawable.img,
            scrollableAppBarHeight = toolbarHeight,
            toolbarOffsetHeightPx = toolbarOffsetHeightPx
        )

    }
}

实现原理其实就一句 实现原理是: colume list 是一直滚动的

     *   唯一的区别是 ttilebar 的offset 什么时候需要执行
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容