material3下拉刷新

285 阅读1分钟

material的下拉刷新迁移到material3。在material3中用nestedScroll方法代替

val pullToRefreshState: PullToRefreshState = rememberPullToRefreshState(),
Box(  
modifier = modifier.fillMaxSize()  
.nestedScroll(pullToRefreshState.nestedScrollConnection)  
.fillMaxSize(),  
)

可能官方的示例代码没写完。用默认的PullToRefreshContainer会发现那个圆圈没有完全隐藏。只要把之前的Modifier.pullRefreshIndicatorTransform() 方法复制一份就正常了。

PullToRefreshContainer(
            state = pullToRefreshState,
            modifier = Modifier
                .align(Alignment.TopCenter)
                .pullRefreshIndicatorTransform(pullToRefreshState)
        )
        
@Composable
fun Modifier.pullRefreshIndicatorTransform(
    state: PullToRefreshState,
    scale: Boolean = false,
) = inspectable(inspectorInfo = debugInspectorInfo {
    name = "pullRefreshIndicatorTransform"
    properties["state"] = state
    properties["scale"] = scale
}) {
    Modifier
        // Essentially we only want to clip the at the top, so the indicator will not appear when
        // the position is 0. It is preferable to clip the indicator as opposed to the layout that
        // contains the indicator, as this would also end up clipping shadows drawn by items in a
        // list for example - so we leave the clipping to the scrolling container. We use MAX_VALUE
        // for the other dimensions to allow for more room for elevation / arbitrary indicators - we
        // only ever really want to clip at the top edge.
        .drawWithContent {
            clipRect(
                top = 0f,
                left = -Float.MAX_VALUE,
                right = Float.MAX_VALUE,
                bottom = Float.MAX_VALUE
            ) {
                this@drawWithContent.drawContent()
            }
        }
        .graphicsLayer {
            translationY = state.verticalOffset - size.height

            if (scale && !state.isRefreshing) {
                val scaleFraction = LinearOutSlowInEasing
                    .transform(state.verticalOffset / state.positionalThreshold)
                    .coerceIn(0f, 1f)
                scaleX = scaleFraction
                scaleY = scaleFraction
            }
        }
}        

刷新数据需要观察pullToRefreshState的isRefreshing,数据刷新完成后还要调用pullToRefreshState.endRefresh()结束刷新动画。

 LaunchedEffect(pullToRefreshState.isRefreshing) {
        if (pullToRefreshState.isRefreshing) {
            pagingItems.refresh()
        }
    }

和paging使用的话就是要判断LazyPagingItems的loadState。loadState.refresh, loadState.append, loadState.prepend。refresh是刷新或者第一次加载,append是加载下一页,prepend可能是加载本地数据的??暂时还没加本地数据库,没做实验。都有三种状态LoadState.Loading,LoadState.Error,LoadState.NotLoading。 例如

//刷新数据结束
if (loadState.refresh !is LoadState.Loading){
    pullToRefreshState.endRefresh()
}
//加载更多数据
if (loadState.append is LoadState.Loading){
    item {  
        LoadingMore()  
        }
}