夏季儿看看:
嵌套滑动(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 什么时候需要执行