「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」
简单了解SwipeRefresh
是一种实现刷新模式的布局,允许用户通过垂直刷手势刷新内容。 他的布局要求其内容可滚动,以便接收垂直滑动事件。不过,可滚动内容不需要是直接的后代。布局,如androidx。组成地基懒惰的LazyColumn是自动可滚动的,但其他的如androidx。组成地基布局列要求您提供androidx。组成地基垂直滚动修改器到该内容。
应用程序应提供onRefresh块,以便在每次完成“刷到刷新”手势时收到通知。该块负责适当地更新状态,通常通过设置SwipeRefreshState。启动“刷新”后,IsRefresh将变为true。刷新完成后,应用程序应设置SwiperFreshState。我的看法是错误的。
如果应用程序希望在滑动手势之外显示进度动画,则可以设置滑动状态。i根据需要进行磨光。
此布局不会剪裁任何内容,包括指示器。如果需要剪辑,应用程序可以提供androidx。组成用户界面。画clipToBounds修饰符。
一般用state 和onRefresh
state:用于控制或观察状态的状态对象。
onRefresh:在完成刷卡刷新手势时调用。
剩下的是一些配置了,有想法的深入了解
state对应着rememberSwipeRefreshState
rememberSwipeRefreshState:创建一个在合成中被记住的状态。
会对isRefreshing的更改而导致更新
参数:isRefreshing
封装流程
我们的目的是封装起来,所以要了解流程
定义状态
val rememberSwipeRefreshState = rememberSwipeRefreshState(isRefreshing = false)
SwipeRefresh
lazyPagingItems: LazyPagingItems<T>,
onRefresh: (() -> Unit) = {}
...
SwipeRefresh(
state = rememberSwipeRefreshState,
onRefresh = {
onRefresh.invoke()
lazyPagingItems.refresh()
}
)
首先定义刷新状态
rememberSwipeRefreshState.isRefreshing =
((lazyPagingItems.loadState.refresh is LoadState.Loading) || isRefreshing)
把LazyColumn放在SwipeRefresh里面
itemContent: LazyListScope.() -> Unit
...
LazyColumn(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
state = listState
) {
//条目布局
itemContent()
}
衍生加载中和 加载错误
//加载更多状态:加载中和加载错误,没有更多
when (loadState.append) {
is LoadState.Loading -> 加载中
is LoadState.Error -> 加载错误
is LoadState.NotLoading -> {
if (loadState.append.endOfPaginationReached) {
//到低了
}
}
}
完整代码
@Composable
fun <T : Any> RefreshList(
lazyPagingItems: LazyPagingItems<T>,
isRefreshing: Boolean = false,
onRefresh: (() -> Unit) = {},
listState: LazyListState = rememberLazyListState(),
itemContent: LazyListScope.() -> Unit,
) {
val rememberSwipeRefreshState = rememberSwipeRefreshState(isRefreshing = false)
//错误页
val err = lazyPagingItems.loadState.refresh is LoadState.Error
if (err) {
ErrorContent { lazyPagingItems.retry() }
return
}
SwipeRefresh(
state = rememberSwipeRefreshState,
onRefresh = {
onRefresh.invoke()
lazyPagingItems.refresh()
}
) {
//刷新状态
rememberSwipeRefreshState.isRefreshing =
((lazyPagingItems.loadState.refresh is LoadState.Loading) || isRefreshing)
//列表
LazyColumn(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
state = listState
) {
//条目布局
itemContent()
//加载更多状态:加载中和加载错误,没有更多
if (!rememberSwipeRefreshState.isRefreshing) {
item {
lazyPagingItems.apply {
when (loadState.append) {
is LoadState.Loading -> LoadingItem()
is LoadState.Error -> ErrorItem { retry() }
is LoadState.NotLoading -> {
if (loadState.append.endOfPaginationReached) {
NoMoreItem()
}
}
}
}
}
}
}
}
}
@Composable
fun ErrorContent(retry: () -> Unit) {
Box(modifier = Modifier.fillMaxSize()) {
Column(modifier = Modifier.align(Alignment.Center)) {
Image(
painter = painterResource(id = R.drawable.stat_notify_error),
contentDescription = null,
colorFilter = ColorFilter.tint(Color.Red),
modifier = Modifier.align(Alignment.CenterHorizontally)
)
Text(
text = "请求出错啦",
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(top = 10.dp)
)
Button(
onClick = { retry() },
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(10.dp),
colors = buttonColors(backgroundColor = AppTheme.colors.themeUi)
) {
Text(text = "重试")
}
}
}
}
@Composable
fun ErrorItem(retry: () -> Unit) {
Button(
onClick = { retry() },
modifier = Modifier.padding(10.dp),
colors = buttonColors(backgroundColor = AppTheme.colors.themeUi)
) {
Text(text = "重试")
}
}
@Composable
fun NoMoreItem() {
Text(
text = "没有更多了",
modifier = Modifier
.padding(10.dp)
.fillMaxWidth(),
textAlign = TextAlign.Center
)
}
@Composable
fun LoadingItem() {
Box(
modifier = Modifier
.fillMaxWidth()
.height(60.dp), contentAlignment = Alignment.Center
) {
CircularProgressIndicator(
color = AppTheme.colors.themeUi,
modifier = Modifier
.padding(10.dp)
.height(50.dp)
)
}
}
ViewModel
private val pager by lazy {
simplePager {
//it = 加载的页数
//根据页数来请求数据
service.getSquareData(it)
}.cachedIn(viewModelScope)
}
var viewStates by mutableStateOf(ViewState(pagingData = pager))
private set
data class ViewState(
val isRefreshing: Boolean = false,
val listState: LazyListState = LazyListState(),
val pagingData: Paging
)
typealias Paging = Flow<PagingData<数据实体>>
渲染UI
val viewStates = remember { viewModel.viewStates }
val squareData = viewStates.pagingData.collectAsLazyPagingItems()
val listState = if (squareData.itemCount > 0) viewStates.listState else LazyListState()
RefreshList(squareData, listState = listState) {
itemsIndexed(squareData) { _, item ->
//Item
}
}