Jetpack Compose技术快速上手

一、什么是Compose?

Jetpack Compose 是Google新推出的用于构建原生 Android 界面的新工具包。它可简化并加快 Android 上的界面开发,使用更少的代码、强大的工具和直观的Kotlin API,快速让应用生动而精彩。

二、Compose的优势

  • 更少的代码
    在Android View系统,实现一个功能需要有XML和Kotlin/Java两部分,而在Compose中不需要拆分两部分,所有代码都使用同一种语言编写并且位于同一个文件中,往往复杂的功能几行代码就能搞定,因此Compose编写的代码简洁且易于维护。
    如:实现一个列表,简单几行代码
@Composable
fun Conversation(messages:List<Message>){
    LazyColumn {
        items(messages){ message->
            MessageCard(message)
        }
    }
}
  • 直观
    Compose使用声明性API,意味着只需描述界面,Compose会负责完成其余工作,应用状态发生变化时,界面会自动智能刷新。

  • 加快应用开发
    Compose兼容现有的所有代码,方便随时随地开始采用。借助全面的Android Studio支持和实时预览功能,可以更快的迭代。

  • 功能强大
    凭借对Android平台API的直接访问和对于Material Design、深色主题、动画等的内置支持,创建精美的应用。

三、开发环境准备

IDE版本:Android Studio Arctic Fox
语言:Kotlin

创建支持Jetpack Compose的新应用

打开Android Studio,依次执行File > New > New Project,在弹出的New Project弹窗中选择Empty Compose Activity,然后点击Next,设置对应Name、PackageName、和保存位置等信息,直接点击【Finish】即可完成Compose工程创建。

选择Empty Compose Activity界面

注:
1.仅支持Kotlin。
2.工程创建后会自动引入Compose相关基础库,如需其他工具包可在项目的Build.gradle配置。

四、Compose可组合函数和预览

新的Compose工程创建好后,在体验Compose开发前我们先来了解两个非常关键的注解。

★ 可组合函数
Jetpack Compose 是围绕可组合函数构建的。这些函数可让您以程序化方式定义应用的界面,只需描述应用界面的外观并提供数据依赖项,而不必关注界面的构建过程(初始化元素,将其附加到父项等)。如需创建可组合函数,只需将 @Composable 注解添加到函数名称中即可。

@Composable
fun MessageCard(name: String) {
    Text(text = "Hello $name!")
}

★ 预览函数
Android Studio允许在IDE中预览可组合函数,无需将应用安装到设备上。使用到的关键注解@Preview

@Preview
@Composable
fun DefaultPreview() {
    MessageCard("Android")
}
使用 Android Studio 预览可组合函数

五、布局

界面元素采用多层次布局,元素中包含其他元素。Compose中通过一个可组合函数调用其他可组合函数来构建界面。

  • 添加文本
    使用可组合函数Text添加一个文本
@Composable
fun MessageCard(msg: Message) {
    Text(text = msg.author)
}
  • 使用Column和Row
    针对多个元素时,怎么布局呢?此时就要用到Column和Row函数了。
    Column函数可以让元素垂直排列。Row函数可使元素水平排列。
@Composable
fun MessageCard(message:Message) {
    //行
    Row {
        //添加一个图片元素
        Image(
            //填充内容
            painter = painterResource(id = R.mipmap.ic_girl),
            contentDescription = "logo",
        )
        //列
        Column{
            Text(text = message.author)
            Text(text = message.body)
        }
    }
}
效果图
  • 添加图片元素
    添加图片元素采用的可组合函数为:Image,见上例子。
  • 使用修饰符配置布局
    在Compose中元素提供了修饰符,通过设置元素的modifier,可以更改元素的大小、布局、外观、互动。
    如下例子中,给Image增加修饰符
//添加一个图片
Image(
     //填充内容
     painter = painterResource(id = R.mipmap.ic_girl),
     contentDescription = "logo",
     //尺寸及形状
     modifier= Modifier
           .padding(top = 2.dp)
           .size(40.dp)                 //图像尺寸
           .clip(CircleShape)       //裁剪形状
    )
采用修饰符后的效果图

六、使用Material Design

Compose的许多界面元素都支持Material Design。
创建的项目中会生成默认主题,支持自定义MaterialTheme。

  • 设置一个Material主题样式
    override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContent {
              //设置主题
              JetpackDemoTheme {
                  ......
              }
          }
      }
    
  • 使用主题颜色
    以为图片添加圆形边框为例:
      //添加一个图片
    Image(
     //填充内容
     painter = painterResource(id = R.mipmap.ic_girl),
     contentDescription = "logo",
     //尺寸及形状
     modifier= Modifier
         .padding(top = 2.dp)
         .size(40.dp)             //图像尺寸
         .clip(CircleShape)       //形状
         .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)//边框样式
    )
    
    设置颜色后效果
  • 排版
    MaterialTheme 中提供了 Material 排版样式,只需将其添加到 Text 可组合项中即可。
    Text(
           text = message.author,
           color = MaterialTheme.colors.secondaryVariant,
           //添加MaterialTheme排版
           style = MaterialTheme.typography.subtitle2
        )
    
  • 设置边框形状
    //设置一个边框
    Surface(shape = MaterialTheme.shapes.medium,
        elevation = 2.dp,
        color = surfaceColor,
        modifier = Modifier.animateContentSize().padding(1.dp).clickable { isExpanded = !isExpanded }
      ){
    Text(text = msg.body)
    }
    
    效果图
  • 启用深色主题
    开发过程中,预览支持启用深色主题(即夜间模式),Jetpack Compose默认能处理深色主题。使用Material颜色、文本和背景时,系统会自动适应深色背景。
    启用方式如下:
    @Preview(name = "Light Mode")//白天模式
    @Preview(showBackground = true,uiMode = Configuration.UI_MODE_NIGHT_YES,name = "Dark Mode")//夜间模式
    @Composable
    fun DefaultPreview() {
        JetpackDemoTheme {
            MessageCard(Message("Android","Jetpack Compose"))
        }
    }
    
同时预览白天模式和夜间模式效果图

七、列表和动画

在实际应用中列表和动画非常常见,这里以简单学习如何利用Compose轻松创建列表和添加动画效果。

  • 创建消息列表
    Compose为我们提供了LazyColumnLazyRow可组合函数,分别对应垂直列表和水平列表。

    @Composable
    fun Conversation(messages:List<Message>){
        //垂直方向列表
        LazyColumn {
            items(messages){ message->
                MessageCard(message)
            }
        }
      }
    //定义数据类
    data class Message(val author: String, val body: String)
    

    静态列表图:


    列表效果图
  • 在展开消息时显示动画效果
    首先将Text的行数设置为一行,当点击时再全部展开。
    先使用可组合函数remember记录没行的展开状态,保存在mutableStateOf中,该值更新后,系统会自动智能重新绘制使用此状态的元素,这一过程又被称为重组

    @Composable
    fun MessageCard(message:Message) {
        ...
        var isExpanded by remember {
                  mutableStateOf(false)
              }
        ...
    }
    

    现在可以通过点击消息更改这个isExpanded变量值,然后根据这个值来修改消息的背景和工行效果。

    @Composable
    fun MessageCard(message:Message) {
        ...
        val surfaceColor: Color by animateColorAsState(
              if (isExpanded) MaterialTheme.colors.primary else MaterialTheme.colors.surface,
          )
        Column{
              ...
              //设置一个边框
              Surface(shape = MaterialTheme.shapes.medium,
                  elevation = 2.dp,
                  color = surfaceColor,
                  modifier = Modifier.animateContentSize()
                      .padding(1.dp)
                      //1.添加一个可点击事件
                      .clickable { isExpanded = !isExpanded }
              ){
                  Text(
                      text = message.body,
                      modifier = Modifier.padding(all = 4.dp),
                      //2.展开时设置行数
                      maxLines=if (isExpanded) Int.MAX_VALUE else 1,
                      //添加MaterialTheme排版
                      style = MaterialTheme.typography.body2
                  )
              }
              ...
        }
        ...
    }
    

    最后上一张带展开收起动画的gif效果图


    添加动画后的列表动态图

最后附上源码地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容