一、 前言
插件化系列文章太难学了,特别是基础不扎实的,本文将从最简单的插件化开始:
本文学习思路:
- Jetpack Compose是新一代的声明式的UI开发框架,是未来的一种趋势,介绍最基础用法学习
- 如何通过代码直接链接点过去查看官方案例代码?
- 插件化中最简单的 纯代码是怎么做到插件化的?(用compose 代码布局来示例)
- 常用传统XML控件和Compose控件对照表
用一个Demo 示例工程,带你入门Compose基础开发:
用一个Demo 示例工程,带你入门Compose插件化开发:
二、示例工程项目介绍:
示例工程不涉及任何架构,最自由式写法,单条目介绍Compose 相关写法
- 示例基本布局,横向写法,竖向写法:(
Row
,Column
,Box
,ConstraintLayout
) - 示例竖向滚动写法:(
Column + Modifier.verticalScroll(rememberScrollState())
) - 示例竖向滚动写法:(
Row = Modifier.horizontalScroll(rememberScrollState())
) - 示例复杂列表相关写法:(
LazyRow
,LazyColumn
,LazyVerticalGrid +GridItemSpan
,LazyHorizontalGrid +GridItemSpan
) - 示例横竖翻页相关写法:(
HorizontalPager
,VerticalPager
) - 示例Tab栏相关写法:(
TabRow
,ScrollableTabRow
) - 示例底部菜单栏相关写法:(
NavHost
,NavigationBar
) - 示例侧滑单栏相关写法:(
ModalNavigationDrawer
) - 示例头部栏相关写法:(
TopAppBar
) - 示例下拉刷新相关写法:(
Modifier.pullToRefresh
) - 示例网络图片相关写法:(
AsyncImage + coil-compose库
) - 示例吸顶栏相关写法:(
stickyHeader
) - 示例收缩固定头部栏相关写法:(
me.onebone:toolbar-compose:2.3.5 库
) - 示例WebView相关写法:(
AndroidView + WebView
) - 示例基础控件相关写法:(
Image,Icon
,Text
,Checkbox
,Switch
,Button
,TextField
,RadioButton
,Slider
,DropdownMenu
,ExposedDropdownMenuBox
,IconButton
,Slider
,Slider
) - 示例Compose插件化相关写法:
示例部分截图:
三、项目详情
因为这是最简单的布局使用,只贴几个案例代码就行了:
- 类似RecyclerView 网格布局:
@Composable
fun girdLayoutExample(innerPadding: PaddingValues, viewModel: ComposeViewModel) {
val datas by viewModel.datas.observeAsState(initial = emptyList())
LazyVerticalGrid(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
// .verticalScroll(rememberScrollState())
, columns = GridCells.Fixed(2)
) {
items(datas) { data ->
Row(
modifier = Modifier
.fillMaxWidth()
.horizontalScroll(rememberScrollState())
.height(80.dp), verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(id = data.resID), contentDescription = "小姐姐", modifier = Modifier
.size(80.dp)
.padding(5.dp), contentScale = ContentScale.Fit
)
AsyncImage(
model = data.imgUrl, contentDescription = "", contentScale = ContentScale.Crop
)
val modelBuilder = ImageRequest.Builder(LocalContext.current).data(data.imgUrl ?: "").crossfade(false).allowHardware(true).build()
Image(
painter = rememberAsyncImagePainter(model = modelBuilder), contentDescription = "小姐姐", modifier = Modifier
.size(80.dp)
.padding(5.dp), contentScale = ContentScale.Crop
)
}
}
}
}
类似RecyclerView 多个Item布局
@Composable<br>fun LazyVerticalGridSpanSample(paddingValues: PaddingValues) {<br> val sections = (0 until 25).toList().chunked(6)<br> val items22 = remember { listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6") }<br><br> LazyVerticalGrid(<br> modifier = Modifier.padding(paddingValues), columns = GridCells.Fixed(3), horizontalArrangement = Arrangement.spacedBy(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)<br> ) {<br> sections.forEachIndexed { index, items -><br> item(span = { GridItemSpan(maxLineSpan) }) {<br> Text(<br> "This is section $index",<br> Modifier<br> .border(1.dp, Color.Gray)<br> .height(80.dp)<br> .wrapContentSize()<br> )<br> }<br> items(items, span = { GridItemSpan(1) }) {<br> Text(<br> "Item $it",<br> Modifier<br> .border(1.dp, Color.Blue)<br> .height(80.dp)<br> .wrapContentSize()<br> )<br> }<br><br> item(span = { GridItemSpan(3) }) {<br> LazyRow(<br> modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp), contentPadding = PaddingValues(8.dp)<br> ) {<br> items(items22) { item -><br> Box(<br> modifier = Modifier<br> .background(Color.Green)<br> .padding(16.dp)<br> .width(120.dp)<br> .height(120.dp), contentAlignment = Alignment.Center<br> ) {<br> Text(text = "AAA $item", color = Color.White)<br> }<br> }<br> }<br> }<br> }<br> }<br>}
3. TabRow
+ HorizontalPager
Tab标签 和 滑动联动翻页:
@SuppressLint("UnrememberedMutableState")<br>@Composable<br>fun tabPage(innerPadding: PaddingValues, viewModel: ComposeViewModel) {<br> var state by remember { mutableStateOf(0) }<br> var statePage = rememberPagerState(initialPage = state) { 5 }<br> val titles = listOf("Tab 1", "Tab 2", "Tab 3 ", "Tab 4 ", "Tab 5 ")<br> val scope = rememberCoroutineScope()<br> Column(<br> modifier = Modifier<br> .padding(innerPadding)<br> .background(Color.Yellow)<br>// .verticalScroll(rememberScrollState())<br> .padding(5.dp)<br> .fillMaxWidth()<br> .fillMaxHeight()<br> ) {<br> TabRow(selectedTabIndex = statePage.currentPage) {<br> titles.forEachIndexed { index, title -><br> Tab(modifier = Modifier.background(Color.Green), selected = state == index, onClick = {<br> scope.launch {<br>// statePage.scrollToPage(index)<br> statePage.animateScrollToPage(index)<br> }<br> }, text = {<br> Text(text = title, maxLines = 2, overflow = TextOverflow.Ellipsis, fontSize = 20.sp, color = Color.Magenta)<br> })<br> }<br> }<br> HorizontalPager(<br> state = statePage, modifier = Modifier<br> .fillMaxWidth()<br> .fillMaxHeight()<br> ) { page -><br> when (page) {<br> 0 -> page1(viewModel)<br> else -> Box(<br> modifier = Modifier<br> .padding(10.dp)<br> .background(Color.Red)<br> .fillMaxWidth()<br> .fillMaxHeight()<br> .aspectRatio(1f), contentAlignment = Alignment.Center<br> ) {<br> Text(text = page.toString(), fontSize = 32.sp)<br> }<br> }<br> }<br> }<br>}
侧滑菜单栏:ModalNavigationDrawer
:
@OptIn(ExperimentalMaterial3Api::class)<br>@Composable<br>fun ModalDrawerExample() {<br> val drawerState = rememberDrawerState(DrawerValue.Closed)<br> val scope = rememberCoroutineScope()<br> // icons to mimic drawer destinations<br> val items = listOf(<br> Icons.Default.AccountCircle,<br> Icons.Default.Email,<br> Icons.Default.Favorite,<br> Icons.Default.AccountBox,<br> Icons.Default.Build,<br> Icons.Default.LocationOn,<br> Icons.Default.Lock,<br> Icons.Default.CheckCircle,<br> Icons.Default.AddCircle,<br> Icons.Default.MailOutline,<br> )<br> val selectedItem = remember { mutableStateOf(items[0]) }<br> val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()<br> Scaffold(topBar = {<br> TopAppBar(modifier = Modifier<br> .fillMaxWidth()<br> .background(Color.Blue)<br> .height(81.dp), colors = mediumTopAppBarColors(<br> containerColor = Color.Blue,<br> titleContentColor = MaterialTheme.colorScheme.primary,<br> ), title = {<br> Row(<br> modifier = Modifier<br> .fillMaxWidth()<br> .fillMaxHeight(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center<br> ) {<br> Text(text = "compose navigation题栏", fontSize = 18.sp, color = Color.Red, style = TextStyle.Default)<br> }<br> }, navigationIcon = {<br> IconButton(onClick = {<br> scope.launch {<br> if (drawerState.isClosed) {<br> drawerState.open()<br> } else {<br> drawerState.close()<br> }<br><br> }<br> }) {<br> Icon(<br> imageVector = Icons.Filled.Menu, contentDescription = "Localized description"<br> )<br> }<br> }, actions = {<br> IconButton(onClick = {<br> /* doSomething() */<br> }) {<br> Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Localized description")<br> }<br> }, scrollBehavior = scrollBehavior<br> )<br><br> }) { innerPadding -><br> ModalNavigationDrawer(modifier = Modifier.padding(innerPadding), drawerState = drawerState, drawerContent = {<br> ModalDrawerSheet(drawerState) {<br> Column(Modifier.verticalScroll(rememberScrollState())) {<br> Spacer(Modifier.height(12.dp))<br> items.forEach { item -><br> NavigationDrawerItem(icon = {<br> Icon(item, contentDescription = null)<br> }, label = {<br> Text(item.name.substringAfterLast("."))<br> }, selected = item == selectedItem.value, onClick = {<br> scope.launch {<br> drawerState.close()<br> }<br> selectedItem.value = item<br> }, modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)<br> )<br> }<br> }<br> }<br> }, content = {<br> Column(<br> modifier = Modifier<br> .fillMaxSize()<br> .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally<br> ) {<br> Text(text = if (drawerState.isClosed) ">>> Swipe >>>" else "<<< Swipe <<<")<br> Spacer(Modifier.height(20.dp))<br> Button(onClick = { scope.launch { drawerState.open() } }) { Text("Click to open") }<br> }<br> })<br> }<br>}
底部菜单栏:NavigationBar
@Composable<br>fun BottomNavigationContent() {<br> var selectedItem by remember { mutableIntStateOf(0) }<br> val items = listOf("首页", "视频", "购物", "设置")<br><br> NavigationBar(<br> modifier = Modifier<br> .fillMaxWidth()<br> .wrapContentHeight()<br> .background(Color.Green)<br> ) {<br> items.forEachIndexed { index, item -><br> NavigationBarItem(modifier = Modifier<br> .wrapContentHeight()<br> .fillMaxWidth()<br> .padding(0.dp)<br> .background(Color.Yellow)<br> .padding(0.dp), icon = {<br> Icon(Icons.Filled.Favorite, contentDescription = item)<br> }, label = { Text(item) }, selected = selectedItem == index, onClick = { selectedItem = index })<br> }<br> }<br>}
阅读全文
资源下载
下载价格免费
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/22666,转载请注明出处。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/22666,转载请注明出处。
评论0