初学Compose:无缝衔接xml的神奇魔法

前言

日常工作,业务需求中的界面布局是至关重要的一部分,长期以来,我们一直都是使用XML布局文件来定义自己的用户界面,但随着Jetpack Compose已经崭露头角,无疑成为了一种强大的UI工具,允许我们以更声明性和可组合的方式构建用户界面。

到目前为止,Compose 正在逐步取代XML ,越来越多的技术团队已经开始普及使用。下面笔者将以初学者的角度出发,简单阐述如何将现有的XML 布局文件转换为Jetpack Compose,实现无缝衔接,以便逐步迁移应用程序的用户界面。

为什么要使用Jetpack Compose

Jetpack ComposeGoogle 官方提供的声明式UI工具包,它引入了一种全新的方式来构建用户界面,基于Kotlin 编写,而Kotlin 作为目前Android的第一生产力语言,这无疑是相得益彰的。由于笔者长期使用XML 编写布局,虽然近期才开始重新学习Compose 并开始实践用于工作和学习当中, 但Compose 必定是未来大势所趋的;虽说目前国内还未完全普及,应用市场上还是有很多应用还在使用着传统的XML布局;

不得不说,现在更新后的AS(笔者这里是Android Studio Giraffe | 2022.3.1 Patch 2 )创建的新项目都是默认使用Compose进行界面编写,完全摒弃了传统XML 界面布局,这已经说明Compose 基本上成为了Google官方主推的UI工具包了;

这时候有人就会说了,既然会成为主流,那它一定有巨大的优势吧;没错,与传统的XML布局文件相比,Jetpack Compose提供了以下优势:

  • 声明性UI编程Compose 允许以声明性的方式描述UI,而不再需要手动操作XML布局文件。这使得UI代码更易于阅读、维护和调试。
  • 可组合性Compose的核心概念是可组合性。可以将小部件组合在一起,构建复杂的UI元素,而不必担心繁琐的布局层次。
  • 实时预览Compose提供了实时预览功能,可以在编写代码的同时查看UI的外观和行为,提高了开发效率。
  • 更少的样板代码 :与XML布局相比,Compose代码通常更少,因为它减少了样板代码的需要。
  • 动态性Compose允许在运行时动态更改UI,这在某些情况下非常有用。

从XML 迁移到Compose

由于最近一个小项目需要将之前的传统布局代码全部迁移为Compose,虽然整体项目布局文件不算太多,但这过程就我而言,非常繁琐,需要自己对传统布局以及Compose相应的替代方案有一定的熟练度,难度不大,不过相对于初学者来说真的挺折磨,毕竟是在旧项目上操刀,尤其是在替换后需要处理布局的差异,要尽可能保持一致,不影响现有效果;话不多说,下面是笔者简单替换的流程图(仅供参考)

步骤1:创建Compose界面

首先,我们需要在Compose 中创建一个等效的界面。对于每个XML布局,我们将创建一个Compose函数,以相同的UI元素作为参数。举个例子,如果我们有一个XML布局文件包含一个TextView 和一个Button,我们可以创建如下的Compose函数:

ini 复制代码
@Composable
fun MyComposeScreen(text: String, buttonText: String) {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = text)
        Button(onClick = { /* 点击处理逻辑 */ }) {
            Text(text = buttonText)
        }
    }
}
步骤2:将数据绑定到Compose界面

接下来,我们需要将数据从XML布局中绑定到Compose界面。这通常涉及创建ViewModel或使用其他数据绑定技术,以确保数据在Compose界面中正确显示。

步骤3:逐步替换XML

一旦Compose界面准备好,并且数据绑定完成,我们可以开始逐步替换XML布局。在每个步骤中,我们将删除XML布局的引用,并在适当的位置调用我们的Compose函数。

这里作为初学者,可以给大家推荐一个网站

  • Which Compose API to use

    在替换的时候,有人肯定想问,如果使用RecyclerView 的话,我们在Compose 中应该用什么呢,ProgressBar我们又该用什么替换呢,等等相关疑问。这个网站的宗旨就是输入传统布局组件它会告诉我们应该用什么,非常实用,直接对症下药,可进一步提高开发效率

步骤4:处理布局差异

在某些情况下,XML布局和Compose之间可能存在布局差异。例如,Compose使用Modifier来管理布局属性,而XML布局使用约束和布局参数。在这种情况下,您需要确保在Compose中正确处理这些差异,以确保UI的外观和行为保持一致。

步骤5:测试和迭代

最后,不要忘记对迁移后的界面进行彻底测试,并根据需要进行迭代和修复。

关于Compose替换XML

在逐步替换XML 的过程中,如果在不中断现有功能的情况下实现无缝衔接的话,需要对XML 布局有一定的理解和认识,所以为了在转化过程中更加顺利流畅,下面笔者XML 中一些常用的布局和组件的替换方案,一起看看在Compose中是怎么实现的吧

这里笔者简单统计了下开发过程中常用的一些布局/组件替换方案,由于代码过多,将以图文的形式展示,方便大家参考

替代xml中的常用布局

我们常用的六大布局,相信大家已经非常熟悉了,就不过多解释啦,下面是它们在Compose的替代方案

1. LinearLayout

XML 中,LinearLayout 用于线性排列其子视图,可以垂直或水平排列。在Compose 中,我们可以使用ColumnRow来实现类似的布局,简单替换代码如下图所示

水平布局也是如此,换成Row即可

2. RelativeLayout

RelativeLayout 允许在XML 中相对于其他视图定位子视图。在Compose 中,我们可以使用BoxModifier相互配合来实现类似的布局,具体得根据实际项目出发,简单替换代码如下图所示

3. FrameLayout

FrameLayout 作为帧布局,主要就是为了堆叠子视图,在Compose 中,可以使用Box 来实现类似的效果,但要注意Box中的子视图是按照层叠顺序绘制的,简单替换代码如下所示

4. GridLayout

GridLayout 用于构建灵活的网格布局,在Compose中,由于之前的Grid组件已经被废弃了,目前需要根据项目本身的需求去自定义布局实现,简单替换代码如下图所示

我们也可以使用LazyVerticalGrid / LacyHorizontalGrid 去实现,它们是Compose中专门用于网格布局的组件,这里简单举一个示例

scss 复制代码
 val itemsList = List(12) { index -> "Item $index" }
    LazyVerticalGrid(columns = GridCells.Fixed(2),
        modifier = Modifier.fillMaxSize(), content = {
            items(itemsList) { item ->
                // 创建并放置子视图
                Text(
                    text = item,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(16.dp)
                )
            }
        })

这里使用LazyVerticalGrid来创建一个垂直网格布局,通过GridCells.Fixed(2)指定了每行的列数为2。然后,我们使用items函数来迭代并放置子视图

5. TableLayout

TableLayoutXML 中用于创建表格布局,通常用于显示数据表格或多行多列的内容。在Compose 中,可以使用LazyColumnLazyRow来创建类似的表格布局,简单替换代码如下图所示:

在Compose中,我们可以使用LazyColumn来创建表格布局,通过嵌套RowText组件来实现表格行和单元格。通过调整items的数量和添加更多的表格行,可以创建一个多行多列的表格布局

6. ConstraintLayout

ConstraintLayout 无疑是我们日常使用最频繁的布局了,它非常强大,可以用来实现一些复杂的界面,在Compose中没有直接对应的布局,需要我们额外引入相对应依赖库来实现约束布局的效果

arduino 复制代码
 implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"

简单替换代码如下图所示

Compose 中,使用ConstraintLayout创建了两个子视图,并使用constrainAs修饰符定义了它们之间的约束关系

替代xml中的常用组件

XML中我们平常会用到很多很多组件,针对这些组件的替换,Compose也提供了相应的解决方案,如下图所示

1. Button,ImageView,TextView

这些组件平常写传统布局的时候一定离不开它们,而它们在Compose中的替代方案也非常简单,分别是:

  • Button组件允许我们创建可交互的按钮,可以自定义文本、样式和点击事件
  • Text组件用于显示文本内容,支持自定义样式和文本格式。
  • Image组件用于显示图像,支持从资源、网络或本地文件加载图像。

简单替换代码如下图所示

2. CardView

CardViewXML 中用于创建卡片式布局,常用于显示列表项或单独的信息块。在Compose 中,可以使用Card组件来实现类似的效果,简单替换代码如下所示

可以设置卡片的elevation(阴影)shape(形状) 等属性

3. RecyclerView

RecyclerViewXML 中用于显示大量数据列表,是Android应用中常见的UI组件之一;在Compose 中,您可以使用LazyColumnLazyRow来创建类似的可滚动列表,简单替换代码如下图所示

使用LazyColumn可以轻松创建可滚动的垂直列表,而LazyRow用于创建水平列表。在Compose中,使用items函数来绑定数据到列表项,并在其中创建列表项的内容

4. ViewPager,ViewPager2

ViewPager、ViewPager2XML 中用于创建可滑动的页面容器,通常用于实现轮播图或分页浏览;在Compose 中没有直接内置的ViewPager 相关组件,这里笔者引入了Accompanist 里的库,使用HorizontalPager、VerticalPager来完成类似的效果

arduino 复制代码
implementation "com.google.accompanist:accompanist-pager-indicators:0.22.0-rc"
    implementation "com.google.accompanist:accompanist-pager:0.22.0-rc"

简单替换代码如下图所示

5. AppBarLayout

AppBarLayoutXML 中常用于创建标题栏,通常包含标题、操作按钮等。在Compose 中,可以使用TopAppBar来实现标题栏效果,简单替换代码如下图所示

TopAppBar可以设置标题、背景颜色、文本颜色以及操作按钮等属性。

6. TabLayout

TabLayoutXML 中用于创建选项卡式布局,通常用于导航不同的标签页。在Compose 中,可以使用TabRow来实现类似的选项卡效果,简单替换代码如下图所示

TabRowTab可以实现选项卡式布局,并在用户与选项卡进行交互时更新界面

7. BottomNavigationView

BottomNavigationViewXML 中常用于底部导航栏,用于切换不同的页面或模块。在Compose 中,可以使用BottomNavigationBottomNavigationItem来实现底部导航栏效果,简单替换代码如下图所示

使用BottomNavigationBottomNavigationItem可以轻松创建底部导航栏,并实现页面切换效果

8. SearchView

SearchViewXML 中用于创建搜索框,通常用于搜索功能。在Compose 中,可以使用TextFieldIcons.Default.Search等组件来创建搜索框,简单替换代码如下图所示

使用TextFieldIcon和状态管理,可以创建具有搜索和清除功能的搜索框,是不是更加方便了呢

9. ScrollView

ScrollViewXML 中用于滚动一个或多个子视图,以便在屏幕上显示超出可见区域的内容。在Compose 中,可以使用LazyColumn来实现类似的滚动效果,简单替换代码如下所示

LazyColumn基本适用于常见的滚动列表,它会根据需要延迟加载内容

10. ProgressBar

ProgressBarXML 中用于显示加载进度,通常用于等待长时间操作或网络请求。在Compose 中,可以使用LinearProgressIndicator来创建加载进度条,简单替换代码如下图所示

使用LinearProgressIndicator可以轻松创建加载进度条,并使用状态管理来控制进度

11. WebView

WebViewXML 中用于显示Web页面或嵌入网页内容。在Compose 中,可以使用AndroidView 来嵌入WebView,简单替换代码如下所示

创建一个嵌入的WebView ,并加载指定的URL

12. Switch

SwitchXML 中用于创建开关按钮,通常用于切换某个设置或状态。在Compose中 ,可以使用Switch组件来实现类似的开关按钮,简单替换代码如下所示

13. DrawerLayout

DrawerLayoutXML 中用于创建抽屉式布局,通常用于侧边栏导航。在Compose 中,可以使用ModalDrawer来实现侧边栏效果,简单替换代码如下图所示

使用ModalDrawer可以实现抽屉式布局,可以控制抽屉的状态并自定义抽屉和内容

以上就是一些常见的组件简单替换方案,具体的要根据项目需求,选择适合的Compose布局元素和修饰符,以满足我们的UI设计需求

最后想说的话

目前来说,国内Compose 并没有完全替代XML 传统布局,但将XML 布局转换为Compose 无疑是一项重要的工作,它可以带来许多好处,包括更好的可维护性、更高的开发效率和更好的用户体验。随着项目版本迭代,通过逐步迁移,我们可以逐渐引入Compose,并在不中断现有功能的情况下实现无缝衔接。

好咯,水文的时光总是非常短暂的,这是一篇关于初学者的简单Compose替换指南,非常基础,希望能带给初学者一些帮助,一起学习进步,共勉!

相关推荐
姑苏风3 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
数据猎手小k6 小时前
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
android·人工智能·机器学习·语言模型
你的小107 小时前
JavaWeb项目-----博客系统
android
风和先行7 小时前
adb 命令查看设备存储占用情况
android·adb
AaVictory.8 小时前
Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
android·java·list
似霰9 小时前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder
大风起兮云飞扬丶9 小时前
Android——网络请求
android
干一行,爱一行9 小时前
android camera data -> surface 显示
android
断墨先生9 小时前
uniapp—android原生插件开发(3Android真机调试)
android·uni-app
无极程序员11 小时前
PHP常量
android·ide·android studio