前言
Jetpack Compose 是用于構(gòu)建原生界面的新款 Android 工具包禁荒。它可簡(jiǎn)化并加快 Android 上的界面開發(fā)备恤。使用更少的代碼辈讶、強(qiáng)大的工具和直觀的 Kotlin API歉闰,快速讓應(yīng)用生動(dòng)而精彩沸版。這是官方對(duì)它的介紹哈雏。2019年Google就推出了Jetpack Compose楞件,并且穩(wěn)定版本即將在2021年7月發(fā)布,所以大家還是有必要提前學(xué)習(xí)一下的裳瘪。
通過這一段時(shí)間的學(xué)習(xí)土浸,了解到Jectpack Compose是一種全新的UI開發(fā)框架,采用了聲明式編程思想彭羹,完全基于Kotlin語(yǔ)言黄伊,并將之前的Xml UI界面渲染那一套邏輯完全廢棄了,所以界面布局/渲染/刷新機(jī)制完全是新的派殷。
需要實(shí)現(xiàn)的功能
Pager組件介紹
Pager組件是專門為使用Jetpack Compose開發(fā)類似頁(yè)面切換布局的一個(gè)庫(kù),類似AndroidView中的Viewpager毡惜,需要注意的是拓轻,當(dāng)前該組件還在實(shí)驗(yàn)階段,所以庫(kù)中的API可能還會(huì)發(fā)生變化经伙,并且所有的API都加了@ExperimentalPagerApi注解
該組件庫(kù)中目前提供了:
1)HorizontalPager:水平方向切換頁(yè)面的組件扶叉,簡(jiǎn)單用法:
// Display 10 items
val pagerState = rememberPagerState(pageCount = 10)
HorizontalPager(state = pagerState) { page ->
? ? ? ? // Our page content
? ? ? ?Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() )
}
通過pagerState可以得到當(dāng)前頁(yè)面:pagerState.currentPage,可以滾動(dòng)到指定頁(yè)面:pagerState.scrollToPage(index),或者pagerState.animateScrollToPage(index)帕膜,但這兩個(gè)方法需要在CoroutineScope使用枣氧,如下:
coroutineScope.launch { pagerState.animateScrollToPage(index)}
2) VerticalPager:豎直方向切換頁(yè)面的組件,基本使用方式同HorizontalPager
3)同ViewPager一樣泳叠,Pager組件同樣可以指定當(dāng)前頁(yè)面兩側(cè)的頁(yè)數(shù)作瞄,通過設(shè)置initOffscreenLimit字段
val pagerState = rememberPagerState( pageCount = 10, initialOffscreenLimit = 2,)
HorizontalPager(state = pagerState) { page -> // ...}
并且,當(dāng)用戶在界面間滑動(dòng)時(shí)危纫,超過該數(shù)量的界面就會(huì)被動(dòng)態(tài)移除宗挥。
Demo實(shí)現(xiàn)
需要上圖中多tab樣式的feed流樣式,需要用到的組件:TabRow + Pager + Indicators + LazyColumn种蝶,對(duì)應(yīng)AndroidView的TabLayout + ViewPager + RecyclerView
環(huán)境準(zhǔn)備:app下的build.gradle中引入如下依賴:
implementation "com.google.accompanist:accompanist-pager:0.13.0"
implementation "com.google.accompanist:accompanist-pager-indicators:0.13.0"
Node:本文基于Jetpack Compose 1.0.0-beta09'
關(guān)鍵代碼:
@ExperimentalPagerApi
@Composable
private fun TabContentScreen(recItems: List<PostData>, followItems: List<PostData>, hotItems: List<PostData>) {
? ? ? ? ? ? ? ?val pages = listOf("熱門", "關(guān)注", "推薦")
? ? ? ? ? ? ? Column {
? ? ? ? ? ? ? ? ? ? val coroutineScope = rememberCoroutineScope()
? ? ? ? ? ? ? ? ? ? val pagerState = rememberPagerState( pageCount = pages.size, initialOffscreenLimit = 2, )
? ? ? ? ? ? ? ? ? ?TabRow( selectedTabIndex = pagerState.currentPage, indicator = {tabPositions ->
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?TabRowDefaults.Indicator( Modifier.pagerTabIndicatorOffset(pagerState, tabPositions), color = Color.White ) },
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?backgroundColor = Color.White, modifier = Modifier.width(210.dp),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? divider = { TabRowDefaults.Divider(color = Color.White) } ) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pages.forEachIndexed { index, title ->
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Tab( selected = pagerState.currentPage == index, onClick = {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?coroutineScope.launch { pagerState.animateScrollToPage(index) }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?},
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?modifier =? Modifier.height(50.dp).background(Color.White),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? selectedContentColor = Color.Black,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unselectedContentColor = Color.Gray ) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Text(title, maxLines = 1,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fontSize = if (pagerState.currentPage == index) 20.sp else 16.sp,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fontWeight = if (pagerState.currentPage == index) FontWeight.Bold else FontWeight.Normal )
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? HorizontalPager( state = pagerState, modifier = Modifier .weight(1f) .fillMaxWidth() ) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LazyColumn(contentPadding = PaddingValues(start = 16.dp, end = 16.dp)) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? val curItems = if (pagerState.currentPage == 0) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? recItems
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } else if (pagerState.currentPage == 1) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?followItems
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? hotItems
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?items(items = curItems) {?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PostCardView(itemData = it)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?}
? ? ? ? ? ? }
}
PS:簡(jiǎn)書的難道沒有直接插入代碼的功能嗎契耿,太難用了