最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - Material3 PullToRefreshBox prevents TopAppBar from expanding - Stack Overflow

programmeradmin1浏览0评论

I want to build a screen using only Material3 components and Jetpack Compose. When I combine the MediumTopAppBar with a PullToRefreshBox and the exitUntilCollapsedScrollBehavior it intercepts my scroll while the TopAppBar is not fully expanded yet. How can I prevent this?

MaterialTheme {
    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        contentWindowInsets = WindowInsets.safeContent,
        topBar = { MediumTopAppBar(title = { Text("Title") }, scrollBehavior = scrollBehavior) },
    ) { padding ->

        val coroutineScope = rememberCoroutineScope()
        var isRefreshing by remember { mutableStateOf(false) }
        val state: PullToRefreshState = rememberPullToRefreshState()

        PullToRefreshBox(
            isRefreshing = isRefreshing,
            onRefresh = {
                isRefreshing = true
                coroutineScope.launch {
                    delay(3.seconds)
                    isRefreshing = false
                }
            },
            state = state,
            indicator = {
                Indicator(
                    modifier = Modifier
                        .align(Alignment.TopCenter)
                        .padding(padding),
                    isRefreshing = isRefreshing,
                    state = state,
                )
            },
        ) {
            ListItems(padding)
        }
    }
}

I want to build a screen using only Material3 components and Jetpack Compose. When I combine the MediumTopAppBar with a PullToRefreshBox and the exitUntilCollapsedScrollBehavior it intercepts my scroll while the TopAppBar is not fully expanded yet. How can I prevent this?

MaterialTheme {
    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        contentWindowInsets = WindowInsets.safeContent,
        topBar = { MediumTopAppBar(title = { Text("Title") }, scrollBehavior = scrollBehavior) },
    ) { padding ->

        val coroutineScope = rememberCoroutineScope()
        var isRefreshing by remember { mutableStateOf(false) }
        val state: PullToRefreshState = rememberPullToRefreshState()

        PullToRefreshBox(
            isRefreshing = isRefreshing,
            onRefresh = {
                isRefreshing = true
                coroutineScope.launch {
                    delay(3.seconds)
                    isRefreshing = false
                }
            },
            state = state,
            indicator = {
                Indicator(
                    modifier = Modifier
                        .align(Alignment.TopCenter)
                        .padding(padding),
                    isRefreshing = isRefreshing,
                    state = state,
                )
            },
        ) {
            ListItems(padding)
        }
    }
}
Share Improve this question asked Mar 27 at 16:30 WirlingWirling 5,4353 gold badges52 silver badges83 bronze badges 2
  • You could try applying the nested scroll modifier on your ListItems. – askSoap Commented Mar 29 at 7:57
  • @Wirling Does below answer resolve your issue? – BenjyTec Commented Mar 31 at 4:06
Add a comment  | 

1 Answer 1

Reset to default 0

Please try to pull the PullToRefreshBox outside of the Scaffold like this:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ScaffoldComposable() {

    val coroutineScope = rememberCoroutineScope()
    var isRefreshing by remember { mutableStateOf(false) }
    val state: PullToRefreshState = rememberPullToRefreshState()
    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()

    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = {
            isRefreshing = true
            coroutineScope.launch {
                delay(3.seconds)
                isRefreshing = false
            }
        },
        state = state,
        indicator = {
            Indicator(
                modifier = Modifier
                    .align(Alignment.TopCenter),
                isRefreshing = isRefreshing,
                state = state,
            )
        }
    ) {
        Scaffold(
            modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
            topBar = {
                MediumTopAppBar(
                    title = { Text("Title") },
                    scrollBehavior = scrollBehavior
                )
            },
        ) { padding ->

            LazyColumn(
                modifier = Modifier.padding(padding)
            ) {
                items(100) {
                    Text(modifier = Modifier.fillMaxWidth(), text = "Item $it")
                }
            }
        }
    }
}

Then, the PullToRefreshBox can only consume any scroll deltas that were not consumed by the Scaffold, meaning that the Indicator will only appear once the MediumTopAppBar is fully expanded.

If you still want the indicator to appear below the MediumTopAppBar, you can apply a padding Modifier as follows:

indicator = {
    Indicator(
        modifier = Modifier
            .padding(top = TopAppBarDefaults.MediumAppBarExpandedHeight)
            .align(Alignment.TopCenter),
        isRefreshing = isRefreshing,
        state = state,
    )
}

Output:

发布评论

评论列表(0)

  1. 暂无评论