jetpack compose NestedScrollConnection

夏季兒看看:
嵌套滑動(NestedScroll) | 你好 Compose
章節(jié)中的nestscroll

示例:伸縮 ToolBar

樣例的代碼地址:Compose 伸縮 ToolBar 的實現(xiàn) | 你好 Compose

看到效果我想實現(xiàn),滾動的時候,向上滾動,先折疊圖片。向下滾動,先滾動列表,以保持最大的可視數(shù)據(jù)窗口

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
            }
        }

        /**
         * 實現(xiàn)原理是: colume list 是一直滾動的
         *   唯一的區(qū)別是 ttilebar 的offset 什么時候需要執(zhí)行
         */
        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
        )

    }
}

實現(xiàn)原理其實就一句 實現(xiàn)原理是: colume list 是一直滾動的

     *   唯一的區(qū)別是 ttilebar 的offset 什么時候需要執(zhí)行
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容