Android Compose實(shí)現(xiàn)底部按鈕以及首頁(yè)內(nèi)容詳細(xì)過(guò)程
最后就行調(diào)用
InitBanner(bannerList= bannerList!!,2000L)
實(shí)現(xiàn)文章列表
數(shù)據(jù)請(qǐng)求就不做過(guò)多贅述了,和banner的數(shù)據(jù)請(qǐng)求一樣,這里主要解析一下Compose的約束布局ConstraintLayout。
Compose約束布局需要導(dǎo)入以下相關(guān)依賴:
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-rc01"
- val img = createRef() 創(chuàng)建一個(gè)依賴點(diǎn),就像xml約束布局里面的id意義昂
- Modifier 使用Modifier的constrainAs進(jìn)行約束調(diào)整
ConstraintLayout( Modifier .fillMaxWidth() .padding(horizontal = 8.dp)) { val img = createRef() Text(text = "作者:${entity.audit}") Image(painter = painterResource(id = R.drawable.icon_un_select), contentDescription = "收藏", Modifier .width(30.dp) .height(30.dp) .constrainAs(img) { end.linkTo(parent.end) }, alignment = Alignment.CenterEnd) }
Item代碼如下
@Composable private fun ArticleListItem(entity: ArticleEntity,modifier: Modifier = Modifier){ Card( shape = RoundedCornerShape(10.dp), backgroundColor = ComposeUIDemoTheme.colors.listItem, elevation = 2.dp,modifier = Modifier.padding(0.dp,10.dp,0.dp,0.dp) ) { Row( Modifier .fillMaxWidth() .clickable { Log.e("articleTAG", "文章點(diǎn)擊") }) { Column(Modifier.fillMaxWidth()) { Text(text = "${entity.title}", Modifier.padding(8.dp,8.dp,8.dp,8.dp), fontSize = 16.sp, color = ComposeUIDemoTheme.colors.textPrimary, maxLines = 1, overflow = TextOverflow.Ellipsis) ConstraintLayout( Modifier .fillMaxWidth() .padding(horizontal = 8.dp)) { val img = createRef() Text(text = "作者:${entity.audit}") Image(painter = painterResource(id = R.drawable.icon_un_select), contentDescription = "收藏", Modifier .width(30.dp) .height(30.dp) .constrainAs(img) { end.linkTo(parent.end) }, alignment = Alignment.CenterEnd) } ConstraintLayout( Modifier .fillMaxWidth() .padding(8.dp)) { val parentView = createRef() Text(text = "${entity.superChapterName}", modifier = Modifier .padding(8.dp) .border( 1.dp, color = Color(R.color.b_666), RoundedCornerShape(8.dp) ) .padding(horizontal = 8.dp, vertical = 2.dp), color = Color.Gray, fontSize = 12.sp ) Text(text = "${entity.niceShareDate}",modifier = Modifier.constrainAs(parentView){ end.linkTo(parent.end) centerVerticallyTo(parent) },color = Color.Gray,fontSize = 12.sp,textAlign = TextAlign.Center) } } } } }
SwipeRefresh下拉刷新
操作列表的時(shí)候下拉刷新和上拉加載更多的操作肯定是少不了的,這里先說(shuō)一下Compose SwipeRefresh下拉刷新組件的使用。
首先導(dǎo)入依賴包:
implementation "com.google.accompanist:accompanist-swiperefresh:$accompanist_pager"http://0.20.2
在ViewModel里面保存一個(gè)記錄刷新狀態(tài)的元素,在刷新請(qǐng)求數(shù)據(jù)過(guò)程中這個(gè)值要變成true進(jìn)行刷新動(dòng)畫的加載,刷新完成之后要變成false關(guān)閉加載動(dòng)畫。
val _isRefreshing: MutableLiveData<Boolean> = MutableLiveData(false) val isRefreshing by viewModel._isRefreshing.observeAsState(false) SwipeRefresh(state = rememberSwipeRefreshState(isRefreshing = isRefreshing), onRefresh = { //將刷新狀態(tài)的值改為true 顯示加載動(dòng)畫 viewModel._isRefreshing.value = true //將請(qǐng)求數(shù)據(jù)的值做改變 讓它能重新請(qǐng)求數(shù)據(jù) requestState.value = "refresh"+System.currentTimeMillis() }) { //填充數(shù)據(jù) Box( Modifier .background(ComposeUIDemoTheme.colors.background) .fillMaxSize() ) { Column(Modifier.fillMaxWidth()) { if (bannerList !== null){ InitBanner(bannerList= bannerList!!,2000L) } if (articleEntityPage !== null){ InitHomeArticleList(articleData = articleEntityPage!!) } } } } LaunchedEffect(key1 = requestState.value, block = { bVM.getBannerList() bVM.getArticleData({ viewModel._isRefreshing.value = false//將刷新狀態(tài)的值改成false 關(guān)閉加載狀態(tài) }) })
首頁(yè)的內(nèi)容一共就這么多了,到這里就能實(shí)現(xiàn)一個(gè) app的地步導(dǎo)航欄以及首頁(yè)了。
LaunchedEffect簡(jiǎn)介
LaunchedEffect存在的意義是允許我們?cè)诒籆omposable標(biāo)注的方法中使用協(xié)程。
@Composable @NonRestartableComposable @OptIn(InternalComposeApi::class) fun LaunchedEffect( key1: Any?, block: suspend CoroutineScope.() -> Unit ) { val applyContext = currentComposer.applyCoroutineContext remember(key1) { LaunchedEffectImpl(applyContext, block) } }
主要參數(shù)是key1,block;key1是觸發(fā)條件,當(dāng)key1發(fā)生改變的時(shí)候就會(huì)執(zhí)行block里面的方法,注意是發(fā)生改變的時(shí)候。
我們一開始在請(qǐng)求數(shù)據(jù)的時(shí)候創(chuàng)建了一個(gè)requestState來(lái)記錄請(qǐng)求狀態(tài),如果這個(gè)狀態(tài)不發(fā)生改變,那么就只會(huì)觸發(fā)一次LaunchedEffect對(duì)數(shù)據(jù)進(jìn)行請(qǐng)求。
//記錄請(qǐng)求狀態(tài) val requestState = remember { mutableStateOf("") } LaunchedEffect(key1 = requestState.value, block = { bVM.getBannerList() bVM.getArticleData({ viewModel._isRefreshing.value = false//將刷新狀態(tài)的值改成false 關(guān)閉加載狀態(tài) }) })
而當(dāng)我們?cè)谒⑿碌臅r(shí)候在onRefres里面改變了這個(gè)參數(shù)的值,那么它就會(huì)觸發(fā)LaunchedEffect重新進(jìn)行數(shù)據(jù)請(qǐng)求。
onRefresh = { //將刷新狀態(tài)的值改為true 顯示加載動(dòng)畫 viewModel._isRefreshing.value = true //將請(qǐng)求數(shù)據(jù)的值做改變 讓它能重新請(qǐng)求數(shù)據(jù) requestState.value = "refresh"+System.currentTimeMillis() }
HorizontalPager簡(jiǎn)介
HorizontalPager類似于AndroidView的ViewPager,用于頁(yè)面承載和滑動(dòng)切換,主要參數(shù)是count頁(yè)面數(shù)據(jù),以及state 當(dāng)前頁(yè)面狀態(tài)。
// Display 10 items HorizontalPager(count = 10) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
通過(guò)scrollToPage可以進(jìn)行頁(yè)面切換,但是只能在協(xié)程里面被執(zhí)行,所以同樣要使用LaunchedEffect進(jìn)行頁(yè)面切換。
//頁(yè)面切換 LaunchedEffect(key1 = indexState.value, block = { pagerState.scrollToPage(indexState.value) })
更多用法以及demo移步這個(gè)鏈接。
源碼地址
到此這篇關(guān)于Android Compose實(shí)現(xiàn)底部按鈕以及首頁(yè)內(nèi)容詳細(xì)過(guò)程的文章就介紹到這了,更多相關(guān)Android內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!