欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Jetpack Compose 基本使用

程序员文章站 2022-03-04 22:54:28
...

什么是 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

Jetpack Compose 基本使用

@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中就可以预览的效果如下:

Jetpack Compose 基本使用

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)
            }
        }
    }
}

文章列表显示如下:

Jetpack Compose 基本使用

增加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)
                }
            }
        }
    }
}

Jetpack Compose 基本使用

总结

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