PullRefreshIndicator circle always displaying on jetpack compose
Asked Answered
C

6

8

A blank grey circle of PullToRefreshContainer is always displaying even first time or after refreshing.

Here is my code

val pullRefreshState = rememberPullToRefreshState()

Box(
    modifier = Modifier
        .fillMaxSize()
        .nestedScroll(connection = pullRefreshState.nestedScrollConnection)
) {
    // Another contents

    PullToRefreshContainer(
        modifier = Modifier.align(alignment = Alignment.TopCenter),
        state = pullRefreshState,
    )
}

Current compose version: 1.6.4

enter image description here

Any help!

Commonage answered 31/3 at 0:43 Comment(3)
having the same issue. Have you solved this?Diena
Work around is add padding at top. But I hope this bug should be fixed soon.Commonage
Add this and you're good to go. Modifier.clipToBounds().pullRefresh(refreshingState)Naamana
A
2

This bug has been fixed in the PullToRefreshBox component, which is available in androidx.compose.material3 version 1.3.0-beta05 or higher. To resolve the issue:

  • Update your Material 3 dependency to at least version 1.3.0-beta05.
  • Replace PullToRefreshContainer with PullToRefreshBox in your code.
val pullToRefreshState = rememberPullToRefreshState()
var isRefreshing by remember { mutableStateOf(false) }

val onRefresh: () -> Unit = {
    isRefreshing = true
    // Simulated delay for refresh operation
    delay(1000)
    isRefreshing = false
}

PullToRefreshBox(
    isRefreshing = isRefreshing,
    onRefresh = { onRefresh() },
    state = pullToRefreshState,
) {
    // Scrollable content goes here
    content()
}
Attentive answered 26/7 at 15:33 Comment(0)
I
1

I has same issue。I solved it。

the code is

var itemCount by remember { mutableIntStateOf(15) }
val pullRefreshState = rememberPullToRefreshState()
if (pullRefreshState.isRefreshing) {
    LaunchedEffect(true) {
        // fetch something
        delay(1500)
        itemCount += 5
        pullRefreshState.endRefresh()
    }
}
Box(Modifier.nestedScroll(pullRefreshState.nestedScrollConnection)) {
    LazyColumn(Modifier.fillMaxSize()) {
        if (!pullRefreshState.isRefreshing) {
            items(itemCount) {
                ListItem({ Text(text = "Item ${itemCount - it}") })
            }
        }
    }
    if (pullRefreshState.progress>0||pullRefreshState.isRefreshing) {
        PullToRefreshContainer(
            modifier = Modifier.align(Alignment.TopCenter),
            state = pullRefreshState,
        )
    }
}

This is fine, but the indicator appears immediately when you first pull it down, and it will still cover the upper components for a moment. I solved it like this, pullRefreshState.progress>0.5f||pullRefreshState.isRefreshing, so that it can be displayed only when the pull down is halfway indicator so it doesn't show up initially.

Innings answered 19/4 at 18:46 Comment(0)
W
1

For me, the easiest way was checking if the scroll state is greater than .5f meaning that the user is at least scrolling

Box(modifier = Modifier.fillMaxSize()) {
        if(pullRefreshState.progress > 0.5f) {
            PullToRefreshContainer(
                state = pullRefreshState,
                modifier = Modifier.align(Alignment.TopCenter)
            )
        }
    }
Waterer answered 3/6 at 19:1 Comment(0)
Y
0

I ended up adding a transperent color to the PullToRefreshContainer container color when the state is not loading like this

        PullToRefreshContainer(
            state = pullToRefreshState,
            modifier = Modifier.align(Alignment.TopCenter),
            containerColor = if (pullToRefreshState.isRefreshing) PullToRefreshDefaults.containerColor else Color.Transparent,
        )

the only problem that it has not so good look when dragging the indicator from top but at least it doesn't stick to top when it is not refreshing

Yokum answered 5/5 at 13:57 Comment(0)
N
0

Avoid passing placement or size related modifier to PullToRefreshContainer to alter refresh indicator use indicator: @Composable (PullToRefreshState) parameter of the this method

 @OptIn(ExperimentalMaterial3Api::class)
    @Composable
    fun Foo(){
        val pullRefreshState = rememberPullToRefreshState()
        LaunchedEffect(key1 = pullRefreshState.isRefreshing) {
            if(pullRefreshState.isRefreshing){
                viewModel.fetchData()
            }
        }
        LaunchedEffect(key1 = viewModel.isFetchingData) {
            // in viewmodel maintain a flag
            // val isFetchingData by mutableStateOf(false)
            if(!viewModel.isFetchingData){
                pullRefreshState.endRefresh()
            }
        }
        Box(modifier = Modifier
            .fillMaxSize()
            .nestedScroll(pullRefreshState.nestedScrollConnection)
        ){
            Content()
            PullToRefreshContainer(
                state = pullRefreshState,
                modifier = Modifier
                    .align(Alignment.TopCenter) ,
            )
        }
    }
Nutcracker answered 9/7 at 13:15 Comment(3)
PullToRefreshState does not have isRefreshing or endRefresh(). You are using an outdated beta version.Flatwise
am on latest stable release i.e 1.2.1 developer.android.com/jetpack/androidx/releases/…Nutcracker
Sorry, my mistake; I misremembered how API tracking works for stable versions. Those experimental APIs have been removed in April 2024, but that removal hasn't reached a stable release yet.Flatwise
C
0

Fixed by this way.

@Composable
fun BoxScope.MyPullToRefreshIndicator(
    state: PullToRefreshState
) {
    val isPresented = remember {
        derivedStateOf {
            state.progress > 0 || state.isRefreshing
        }
    }

    if (isPresented.value) {
        PullToRefreshContainer(
            modifier = Modifier
                .align(alignment = Alignment.TopCenter),
            state = state,
        )
    }
}
Commonage answered 2/8 at 6:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.