Jetpack Compose 初体验

什么是 Jetpack Compose

Jetpack Compose是Google I/O 2019 发布的Andorid UI框架,它不同于Andorid常见的Xml+命令式Coding的UI开发范式,而是基于Kotlin的DSL实现了一套类似React的声明式UI框架。Jetpack Compose目前仍然处于pre-alpha版本,目标是2020年能够发布稳定的Beta版本。伴随React Native、Flutter等大前端框架的兴起以及Jetpack Compose、SwiftUI等native框架的出现,声明式UI正逐渐成为客户端UI开发的新趋势。我们通过一个小sample来学习和体验一下Jetpack Compose带来的新的开发方式

开发环境

由于Jetpack Compose还未正式发布,需要使用Preview版的AndroidStudio进行体验:

  • Android Studio4.0 Canary3
  • targetSdkVersion 29

新建Project,选择 Empty Compose Activity

@Compose组件

Compose的API非常友好,通过为函数添加@Composable注解,将其声明为一个可以在DSL中使用的UI组件。之后在Activity中可以通过setContent{...}方法使用DSL声明UI布局:

//MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Greeting(name = "Android")
        }
    }
}

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

使用IDE进行Priview

从Android Studio4.0 Canary1起,可以在IDE中对@Comopse组件进行预览。在@Compose函数上添加@Preview即可进行预览。需要注意的是用Compose的代码发生变更后经过build才能在预览中反映出来,不像xml的预览那么实时,这是因为compose的代码需要经过编译生成新的class后才能再次运行从而生效,而xml的变动是无需经过编译的。

另外需注意的是@Preview的组件不能有参数,所以Greeting组件需要向下面这样进行预览

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

@Preview
@Composable
fun PreviewGreeting() {
    Greeting("Android")
}

在IDE中就可以预览的效果如下:

Sample实现

了解了基本使用之后,我们实现一个简单的Sample,用来显示文章列表:

dataclass

首先,定义sample中需要使用的data class

//Article.kt
data class Article(
    val id: String,
    val title: String,
    val url: String,
    val user: User
)
//User.kt
data class User(
    val id: String,
    val name: String,
    val profileImageUrl: String
)

ArticleItem

接下来实现文章列表Item的UI,由于用到了DrawImage组件,先在build.gradle中添加以下依赖

dependencies{
    implementation 'androidx.ui:ui-foundation:0.1.0-dev03'
}

相比传统的通过Class定义自定义控件的方式,定义Compose组件只需要定义一个function:

@Composable
fun ArticleItem(article: Article) {
    val image = +imageResource(R.drawable.ic_header)
    val typography = +MaterialTheme.typography()

    Row(modifier = Spacing(16.dp)) {
        Container(modifier = Size(60.dp, 60.dp)) {
            DrawImage(image = image)
        }
        Column(modifier = ExpandedWidth wraps Spacing(right = 16.dp, left = 16.dp)) {
            Text(article.title, style = typography.h6)
            Text(article.user.name, modifier = Spacing(top = 4.dp), style = typography.subtitle2)
        }
    }
}

function内部可以调用其他的@Compose的function,从而实现有层级的UI。上面代码中使用到下列Compose组件:

  • Row
    • 水平并排显示多个组件,类似于orientation为horizontal的LinearLayout
  • Container
    • 可以按照指定大小显示内部元素,常用来显示DrawImage等
  • DrawImage
    • 用来显示Image
  • Column
    • 垂直并排显示显示多个组件,类似于orientation为vertical的LinearLayout
  • Text
    • 显示文本,可以通过style指定TextSize
  • Spacing
    • 用来设置margin

可见,用Andorid传统的布局方式不同,ComposeI采用类似H5或Flutter中广泛使用的Flexbox布局方式。

ArticleList

由Item构成文章列表

//ArticleList.kt
@Composable
fun ArticleList(articles: List<Article>) {
    VerticalScroller {
        Column {
            articles.forEach { article ->
                Card(
                    modifier = Spacing(4.dp) wraps Expanded,
                    shape = RoundedCornerShape(8.dp)
                ) {
                    ArticleItem(article = article)
                }
            }
        }
    }
}
  • VerticleScroller
    • 垂直方向的滚动
  • Card
    • 相当于Android的CardView

MaiActivity

在MainAcitity中显示文章列表:

//MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val articles = mutableListOf<Article>()
        repeat(11) {
            articles.add(
                Article(
                    id = "$it",
                    title = "Kotlin入门",
                    url = "http://www.exsample.com/articles/$it",
                    user = User(id = "123", name = "第${it}讲...", profileImageUrl = "")
                )
            )
        }

        setContent {
            MaterialTheme {
                ArticleList(articles = articles)
            }
        }
    }
}

文章列表显示如下:

增加Toolbar

最后我们可以在顶部增加Toolbar,让显示效果更完善。可以通过Column将Toolbar放置在顶部:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            MaterialTheme { 
                Column {
                    TopAppBar(title = {
                        Text("Kotlin入门")
                    })
                    ArticleList(articles = articles)
                }
            }
        }
    }
}

总结

通过上面的sample我们了解了如何使用Jetpack Compose进行一个简单的UI布局。但Compose绝不仅仅是用来布局的工具,否则和Anko有什么区别呢?它真正强大的是包晗状态管理在内的一整套声明式UI的编程范式,关于这些的学习我们后面再另开文章介绍。Jetpack Compose吸收了很多前端框架的设计思想,例如用function替代class明显是来自React的函数式组件的灵感,这些变化会让习惯与写OOP程序的同学们有一种耳目一新的感觉,但是不可否认的是现阶段无论功能和性能上,Jetpack Compose距离”可用”还有很大一段距离,相信不久的未来Beta版的推出会给我们带来更多惊喜。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fundroid

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值