Compose插件化:一个Demo带你入门Compose,同时带你入门插件化开发

一、 前言

插件化系列文章太难学了,特别是基础不扎实的,本文将从最简单的插件化开始:

本文学习思路:

  1. Jetpack Compose是新一代的声明式的UI开发框架,是未来的一种趋势,介绍最基础用法学习
  2. 如何通过代码直接链接点过去查看官方案例代码?
  3. 插件化中最简单的 纯代码是怎么做到插件化的?(用compose 代码布局来示例)
  • 常用传统XML控件和Compose控件对照表 Sheet1.png

用一个Demo 示例工程,带你入门Compose基础开发:
用一个Demo 示例工程,带你入门Compose插件化开发:

二、示例工程项目介绍:

示例工程不涉及任何架构,最自由式写法,单条目介绍Compose 相关写法

  • 示例基本布局,横向写法,竖向写法:(Row,Column,Box,ConstraintLayout
  • 示例竖向滚动写法:(Column + Modifier.verticalScroll(rememberScrollState())
  • 示例竖向滚动写法:(Row = Modifier.horizontalScroll(rememberScrollState())
  • 示例复杂列表相关写法:(LazyRowLazyColumnLazyVerticalGrid +GridItemSpanLazyHorizontalGrid +GridItemSpan
  • 示例横竖翻页相关写法:(HorizontalPagerVerticalPager
  • 示例Tab栏相关写法:(TabRowScrollableTabRow
  • 示例底部菜单栏相关写法:(NavHostNavigationBar
  • 示例侧滑单栏相关写法:(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插件化相关写法:

示例部分截图:

本文涉及到demo示例:大多都是官方代码example,下文中会带大家直接查看官方示例代码

项目地址github
项目地址gitee

三、项目详情

因为这是最简单的布局使用,只贴几个案例代码就行了:

  1. 类似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/22666,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?