如何从 onScrollPositionChanged 回调中更改 VerticalScroller 的 scrollerPosition?

How can I alter VerticalScroller's scrollerPosition from onScrollPositionChanged callback?

正如下面的代码所示,我有一个回调,我想在其中收集 VerticalScroller 的位置,但如果我这样做,VerticalScrollers 小部件将不再滚动,因为在源代码中 VerticalScroller,初始回调调用了 VerticalScrollerscrollerPosition。无法从我要使用它的回调中访问该值。有没有快速调用 scrollerPosition 或使滚动行为继续的方法? (不创建递归 "race" 条件?)

@Composable
fun StationsScreen(deviceLocation: LocationData, openDrawer: () -> Unit)
{

    var scrollPosition = ScrollPosition(0.px,0.px)

    FlexColumn {
        inflexible {
            TopAppBar(
                title = {Text(text = "Stations")},
                navigationIcon = {
                    VectorImageButton(id = R.drawable.ic_baseline_menu_24) {
                        openDrawer()
                    }
                }
            )
        }
        inflexible {
            Column (
                mainAxisSize = LayoutSize.Expand,
                crossAxisSize = LayoutSize.Expand
            ){

                LocationWidget(deviceLocation)
            }
        }
        inflexible {
            Column(
                mainAxisSize = LayoutSize.Expand,
                crossAxisSize = LayoutSize.Expand
            ){
                PushWidget(){
                    deviceLocation.lat++
                    deviceLocation.lng++
                }
            }
        }
        inflexible{
            Column(
                mainAxisSize = LayoutSize.Expand,
                crossAxisSize = LayoutSize.Expand
            ) {
                ScrollPosWidget(scrollPosition = scrollPosition)
            }
        }
        flexible(flex = 1f)
        {
            VerticalScroller (onScrollPositionChanged = { px: Px, px1: Px ->
                scrollPosition.posX = px
                scrollPosition.maxX = px1
            }){

                Column {

                    for(i in 0..20) {
                        HeightSpacer(16.dp)
                        imageBank.forEach { imageItem: ImageItem ->

                            Text(text = imageItem.title ?: "<Empty>")

                            Divider()
                        }
                    }
                }
            }
        }
    }
}

--- compose源码中VerticalScroller Widget的定义:

@Composable
fun VerticalScroller(
    scrollerPosition: ScrollerPosition = +memo { ScrollerPosition() },
    onScrollPositionChanged: (position: Px, maxPosition: Px) -> Unit = { position, _ ->
        scrollerPosition.value = position
    },
    isScrollable: Boolean = true,
    @Children child: @Composable() () -> Unit
) {
    Scroller(scrollerPosition, onScrollPositionChanged, true, isScrollable, child)
}

实际上我找到了解决问题的方法...(我有时被教导要跳出框框思考...)所以...

在我的 @Compose 函数中,我实际上需要创建自己的 scrollerPosition 实例,并在调用 VerticalScroller 时使用它来更改位置。我担心这会导致递归 "race" 调用情况,但这取决于在 Scroller 的逻辑中何时调用 onScrolledPostionChanged。如果在 scrollerPosition.position 改变值时调用 onScrolledPositionChanged,您可能会得到递归的 "race" 条件。但显然不是。

所以我的改动基本是这样的:

@Composable
fun StationsScreen(deviceLocation: LocationData, openDrawer: () -> Unit)
{

    var scrollPosition = ScrollPosition(0.px,0.px)

    var myScrollerPosition = +memo{ ScrollerPosition ()}  //<--- make my own scrollerPosition

    FlexColumn {
        inflexible {
            TopAppBar(
                title = {Text(text = "Stations")},
                navigationIcon = {
                    VectorImageButton(id = R.drawable.ic_baseline_menu_24) {
                        openDrawer()
                    }
                }
            )
        }
        inflexible {
            Column (
                mainAxisSize = LayoutSize.Expand,
                crossAxisSize = LayoutSize.Expand
            ){

                LocationWidget(deviceLocation)
            }
        }
        inflexible {
            Column(
                mainAxisSize = LayoutSize.Expand,
                crossAxisSize = LayoutSize.Expand
            ){
                PushWidget(){
                    deviceLocation.lat++
                    deviceLocation.lng++
                }
            }
        }
        inflexible{
            Column(
                mainAxisSize = LayoutSize.Expand,
                crossAxisSize = LayoutSize.Expand
            ) {
                ScrollPosWidget(scrollPosition = scrollPosition)
            }
        }
        flexible(flex = 1f)
        {
            VerticalScroller (
                scrollerPosition = myScrollerPosition,
                onScrollPositionChanged = { px: Px, px1: Px ->
                    scrollPosition.posX = px
                    scrollPosition.maxX = px1
                    myScrollerPosition.value = px //<-- remember to set the new value here

                    // You can now use the difference of maxX and posX to load
                    // new items into the list...

            }){

                Column {

                    for(i in 0..20) {
                        HeightSpacer(16.dp)
                        imageBank.forEach { imageItem: ImageItem ->

                            Text(text = imageItem.title ?: "<Empty>")

                            Divider()
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun LocationWidget(locationData: LocationData){

    Surface {
        Padding(padding = 8.dp) {
            Text(text = "${locationData.lat}, ${locationData.lng}")
        }
    }

}

@Composable
fun PushWidget(action: () -> Unit){

    Surface {
        Padding(padding = 8.dp) {
            Button(text = "Click Me!", onClick = action)
        }
    }
}

@Composable
fun ScrollPosWidget(scrollPosition: ScrollPosition){
    Surface {
        Padding(padding = 8.dp) {
            Text(text = "posX=${scrollPosition.posX}, maxX=${scrollPosition.maxX}")
        }
    }
}

RG