当前位置: 首页 > article >正文

Android Compose list 下拉刷新、上拉加载更多

前言:本文使用UI框架Compose +Paging+Swiperefresh实现列表的下拉刷新,上拉加载更多功能

一、添加相关库包括viewModel ,Paging,Swiperefresh的Compose库


    implementation ("androidx.emoji2:emoji2:1.3.0")
    //network & serialization
    implementation ("com.google.code.gson:gson:2.9.0")
    implementation ("com.squareup.retrofit2:converter-gson:2.9.0")
    implementation ("com.squareup.retrofit2:retrofit:2.9.0")//
    implementation ("com.squareup.okhttp3:logging-interceptor:4.9.3")
    //swiperefresh 的compose 版本
    implementation ("com.google.accompanist:accompanist-swiperefresh:0.30.1")
    // paging 3 的compose 版本
    implementation ("androidx.paging:paging-compose:1.0.0-alpha18")
    //这个可以在Compose中得到viewmodel
    implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
    //coil Compose 图片加载库
    implementation ("io.coil-kt:coil-compose:2.0.0-rc01")

二、MainActivity


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeDemoTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Greeting("Android")
                }
            }
        }
    }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    ListContent()
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    ComposeDemoTheme {
        Greeting("Android")
    }
}


@Composable
fun ListContent(){
    val viewModel:GithubViewModel= viewModel()
    val lazyPagingItems=viewModel.repositorPager.collectAsLazyPagingItems()
    val state:LazyListState= rememberLazyListState()
    SwipeRefresh(state =rememberSwipeRefreshState(lazyPagingItems.loadState.refresh is LoadState.Loading&&lazyPagingItems.itemCount > 0) ,
        onRefresh = { lazyPagingItems.refresh() }) {
        LazyColumn(state =state,
            contentPadding = PaddingValues(10.dp),
            verticalArrangement = Arrangement.SpaceEvenly){
               items(items=lazyPagingItems){item->
                   item?.let {
                       RepositorCard(it)
                   }
               }
               if(lazyPagingItems.loadState.append is LoadState.Loading){
                    item {
                        Box(modifier = Modifier
                            .fillMaxWidth()
                            .height(50.dp)){
                            CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
                        }
                    }
                }

        }
        if(lazyPagingItems.loadState.refresh is LoadState.Loading){
            if(lazyPagingItems.itemCount==0){
                Box(modifier = Modifier.fillMaxSize()) {
                    CircularProgressIndicator(modifier = Modifier.align(alignment = Alignment.Center))
                }
            }
        }else if(lazyPagingItems.loadState.refresh is LoadState.Error){
            //加载失败的错误页面
            Box(modifier = Modifier.fillMaxSize()) {
                Button(modifier = Modifier.align(alignment = Alignment.Center),
                    onClick = { lazyPagingItems.refresh() }) {
                    Text(text = "加载失败!请重试")
                }
            }
        }
    }
}

 @Composable
fun RepositorCard(repositorItem: RepositorItem) {
    Card(modifier = Modifier
        .fillMaxWidth()
        .padding(8.dp)) {
        Row(modifier = Modifier
            .fillMaxWidth()
            .height(88.dp)) {
            Spacer(modifier = Modifier.width(10.dp))
            Surface(shape = CircleShape, modifier = Modifier
                .size(66.dp)
                .align(Alignment.CenterVertically)) {
                AsyncImage(model = repositorItem.owner.avatar_url,
                    contentDescription = "",
                    contentScale = ContentScale.Crop)
            }

            Spacer(modifier = Modifier.width(15.dp))
            Column(modifier = Modifier.fillMaxWidth()) {
                Spacer(modifier = Modifier.height(8.dp))
                Text(text = repositorItem.name,
                   )
                Text(text = repositorItem.full_name, style = MaterialTheme.typography.bodyMedium)
            }
        }
    }
}

三、MyPagingSource

class MyPagingSource(
    val githubService: GithubService = getGithubService(),
    val words: String,
) : PagingSource<Int, RepositorItem>() {

    override fun getRefreshKey(state: PagingState<Int, RepositorItem>): Int? {
        return state.anchorPosition?.let {
            val anchorPage = state.closestPageToPosition(it)
            anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
        }
    }

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, RepositorItem> {
        try {
            val nextPage: Int = params.key ?: 1
            val repositorRst = githubService.searchRepositors(words, nextPage, 20)
            return LoadResult.Page(
                data = repositorRst.items,
                prevKey = if (nextPage == 1) null else nextPage - 1,
                nextKey = if (repositorRst.items.isEmpty()) null else nextPage + 1
            )
        }catch (e:Exception){
            return LoadResult.Error(e)
        }
    }

四、GithubViewModel

class GithubViewModel:ViewModel() {
    val repositorPager = Pager(config = PagingConfig(pageSize = 6)){
        MyPagingSource(getGithubService(),"compose")
    }.flow.cachedIn(viewModelScope)

}

Demo下载:https://download.csdn.net/download/ange_li/90152118


http://www.kler.cn/a/444962.html

相关文章:

  • oracle client linux服务器安装教程
  • OpenSSL 心脏滴血漏洞(CVE-2014-0160)
  • AFL-Fuzz 的使用
  • Python 爱心代码实现动态爱心图案展示
  • [IT项目管理]九.项目质量管理
  • Unity 上好用的插件
  • JS实现在线预览HTML文件
  • 分布式刚度编织,让可穿戴触觉更出色 ——Haptiknit
  • Visio——同一个工程导出的PDF文件大小不一样的原因分析
  • 深度学习笔记27_RNN实现阿尔茨海默病诊断(pytorch)
  • 基础2:值类型与右值引用
  • React和Three.js结合-React Three Fiber
  • 前端面经每日一题Day16
  • 华为ensp--BGP路径选择-AS_Path
  • 电力场景输电塔分割数据集labelme格式288张4类别
  • AI 在游戏领域的革命性技术
  • 人工智能 (AI) 模型的数据泄露问题
  • Serverless监控和调试、持续集成和持续部署
  • 小红书关键词搜索采集 | AI改写 | 无水印下载 | 多维表格 | 采集同步飞书
  • MySQL日期类型
  • 如何高效使用 Facebook Business Manager (商务管理平台)
  • AI开发:支持向量机(SVM)鸢尾花模型入门教程- Python 机器学习
  • linux cpu 管理
  • Unity Post请求发送fromdata数据content-type
  • 企业为何需要可视化数据分析系统
  • 迅为RK3576开发板接口丰富4G/5G、wifi6、多网口、NPU等