在今年的Google/IO大会上,亮相了一个全新的 Android 原生 UI 开发框架-Jetpack Compose, 与苹果的SwiftIUI同样,Jetpack Compose是一个声明式的UI框架,随着了今年安卓和苹果两大移动平台相继推出本身的UI开发框架Jetpack Compose 和SwiftIUI,标志着移动操做系统正式全面拥抱声明式 UI 开发模式。java
其实声明式 UI 并非什么新技术,早在 2006 年,微软就已经发布了其新一代界面开发框架 WPF,其采用了 XAML 标记语言,支持双向数据绑定、可复用模板等特性。android
2010 年,由诺基亚领导的 Qt 团队也正式发布了其下一代界面解决方案 Qt Quick,一样也是声明式,甚至 Qt Quick 起初的名字就是 Qt Declarative。QML 语言一样支持数据绑定、模块化等特性,此外还支持内置 JavaScript,开发者只用 QML 就能够开发出简单的带交互的原型应用。git
声明式 UI 框架近年来飞速发展,而且被 Web 开发带向高潮。React 更是为声明式 UI 奠基了坚实基础并一直引领其将来的发展。随后 Flutter 的发布也将声明式 UI 的思想成功带到移动端开发领域...github
声明式UI的意思就是,描述你想要一个什么样的UI界面,状态变化时,界面按照先前描述的从新“渲染”便可获得状态绝对正确的界面,而不用像命令同样,告诉程序一步一步该干什么,维护各类状态。扯远了,这个并非今天文章的重点,稍微了解一下就好,其余的就不在本文延伸。关于声明式的更多介绍,建议看看这篇文章:zhuanlan.zhihu.com/p/68275232编程
咱们回到本文的重点Jetpack Compose。微信
Jetpack Compose 是一个用于构建原生Android UI 的现代化工具包,它基于声明式的编程模型,所以你能够简单地描述UI的外观,而Compose则负责其他的工做-当状态发生改变时,你的UI将自动更新。因为Compose基于Kotlin构建,所以能够与Java编程语言彻底互操做,而且能够直接访问全部Android和Jetpack API。它与现有的UI工具包也是彻底兼容的,所以你能够混合原来的View和如今新的View,而且从一开始就使用Material和动画进行设计。app
每当咱们学习一门新的语言,咱们都是从一个hello world
开始,今天咱们也从一个hello world
来开始Jetpack Compose 吧! 要想得到Jetpack Compose 的最佳体验,咱们须要下载最新版本的Android Studio 预览版本(即Android Studio 4.0)。由于Android Studio 4.0 添加了对Jetpack Compose 的支持,如新的Compose 模版和Compose 及时预览。框架
使用Jetpack Compose 来开始你的开发工做有2种方式:jvm
接下来分别介绍一下这两种方式。maven
若是你想在现有的项目中使用Jetpack Compose,你须要配置一些必须的设置和依赖:
(1)gradle 配置
在app目录下的build.gradle
中将app支持的最低API 版本设置为21或更高,同时开启Jetpack Compose enable
开关,代码以下:
android {
defaultConfig {
...
minSdkVersion 21
}
buildFeatures {
// Enables Jetpack Compose for this module
compose true
}
...
// Set both the Java and Kotlin compilers to target Java 8.
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
复制代码
(2) 使用试验版Kotlin-Gradle
插件
Jetpack Compose 须要试验版的Kotlin-Gradle
插件,在根目录下的build.gradle
添加以下代码:
buildscript {
repositories {
google()
jcenter()
// To download the required version of the Kotlin-Gradle plugin,
// add the following repository.
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
...
dependencies {
classpath 'com.android.tools.build:gradle:4.0.0-alpha01'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.60-eap-25'
}
}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
}
}
复制代码
(3) 添加Jetpack Compose工具包依赖项
在app目录下的build.gradle
添加Jetpack Compose 工具包依赖项,代码以下:
dependencies {
// You also need to include the following Compose toolkit dependencies.
implementation 'androidx.ui:ui-tooling:0.1.0-dev02'
implementation 'androidx.ui:ui-layout:0.1.0-dev02'
implementation 'androidx.ui:ui-material:0.1.0-dev02'
...
}
复制代码
ok,到这儿准备工做就完毕,就能够开始写代码了,可是前面说了,还有一种方式接入Jetpack Compose ,咱们来一块儿看看。
比起在现有应用中接入Jetpack Compose ,建立一个支持Jetpack Compose 的新项目则简单了许多,由于Android Studio 4.0 提供了一个新的Compose 模版,只要选择这个模版建立应用,则全部上面的那些配置项都自动帮咱们完成了。
建立一个支持Jetpack Compose 的应用,以下几个步骤就能够了:
Start a new Android Studio project
,若是你已经打开了Android Studio 项目,则在顶部菜单栏选择File > New > New Project
Select a Project Template
窗口,选择Empty Compose Activity
而且点击下一步Configure your project
窗口,作以下几步:项目名称
, 包名
和保存位置
Minimum API level
下拉菜单中,选择21或者更高Finish
如今,你就可使用Jetpack Compose 来编写你的应用了。
在MainActivity.kt
中添加以下代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text("Hello, Android技术杂货铺")
}
}
}
复制代码
Jetpack Compose是围绕composable
函数来构建的。这些函数使你能够经过描述应用程序的形状和数据依赖,以编程方式定义应用程序的UI,而不是着眼于UI的构建过程。要建立composable
函数,只须要在函数名前面加上一个@composable
注解便可, 上面的Text
就是一个composable
函数。
composable
函数一个composable
函数只能在另外一个composable
函数的做用域里北调用,要使一个函数变为composable
函数,只需在函数名前加上@composable
注解,咱们把上面的代码中,setContent
中的部分移到外面,抽取到一个composable函数中,而后传递一个参数name
给 text
元素。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Greeting("Android技术杂货铺")
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
复制代码
UI元素是分层级的,元素包含在其余元素中。在Jetpack Compose中,你能够经过从其余composable
函数中调composable
函数来构建UI层次结构。
在Android的xml
布局中,若是要显示一个垂直结构的布局,最长用的就是LinearLayout
, 设置android:orientation
值为vertical
, 子元素就会垂直排列,那么,在Jetpack Compose 中,如何来实现垂直布局呢?先添加几个Text
来看一下。
在上面的例子中,咱们添加了一个Text
显示文本,如今咱们添加三个文本,代码以下:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NewsStory()
}
}
}
@Composable
fun NewsStory() {
Text("我超❤️JetPack Compose的!")
Text("Android技术杂货铺")
Text("依然范特西")
}
复制代码
从上图能够看到,咱们添加了3个文本,可是,因为咱们尚未提供有关如何排列它们的任何信息,所以三个文本元素相互重叠绘制,使得文本不可读。
要使重叠绘制的Text
文本可以垂直排列,咱们就须要使用到Column
函数,写过flutter的同窗看起来是否是很眼熟?是的,跟flutter里面的Column Widget 名字和功能彻底同样,甚至连他们的属性都一摸同样。
@Composable
fun NewsStory() {
Column { // 添加Column,使布局垂直排列
Text("我超❤️JetPack Compose的!")
Text("Android技术杂货铺")
Text("依然范特西")
}
}
复制代码
效果以下:
能够看到,前面重叠的布局,如今已经垂直排列了,可是,默认状况下,从左上角开始,一个接一个的排列,没有任何间距。接下来,咱们给Column
设置一些样式。
Column
添加样式在调用Column()
时,能够传递参数给Column()
来配置Column
的大小、位置以及设置子元素的排列方式。
@Composable
fun NewsStory() {
Column (
crossAxisSize = LayoutSize.Expand,
modifier = Spacing(16.dp)
){ // 添加Column,使布局垂直排列
Text("我超❤️JetPack Compose的!")
Text("Android技术杂货铺")
Text("依然范特西")
}
}
复制代码
如上图所示,咱们填充了padding,其余效果几乎一摸同样, 上面代码中的设置属性解释以下:
crossAxisSize
: 指定Column
组件(注:Compose中,全部的组件都是composable函数,文中的组件都是指代composable函数
)在水平方向的大小,设置 crossAxisSize
为LayoutSize.Expand
即表示Column宽度应为其父组件容许的最大宽度,至关于传统布局中的match_parant
,还有一个值为LayoutSize.Wrap
,看名字就知道,包裹内容,至关于传统布局中的wrap_content
。
modifier:
使你能够进行其余格式更改。在这种状况下,咱们将应用一个Spacing
修改器,该设置将Cloumn
与周围的视图产生间距。
在原来的安卓原生布局中,显示图片有相应的控件ImageView
,设置本地图片地址或者Bitmap
就能展现,在Jetpack Compose 中该如何显示图片呢?
咱们先下载这张图片到本地,添加到资源管理器中,命名为header.png
, 咱们更改一下上面的NewsStory ()
方法,先从资源文件夹获取图片image,而后经过DrawImage()
将图片绘制出来:
@Composable
fun NewsStory() {
// 获取图片
val image = +imageResource(R.mipmap.header)
Column (
crossAxisSize = LayoutSize.Expand,
modifier = Spacing(16.dp)
){ // 添加Column,使布局垂直排列
// 显示图片
DrawImage(image)
Text("我超❤️JetPack Compose的!")
Text("Android技术杂货铺")
Text("依然范特西")
}
}
复制代码
能够看到,图片不会按正确的比列显示,接下来,咱们来修复它。
图片已添加到布局中,但会展开以填充整个视图,并和文本是拼叠排列,文字显示在上层。要设置图形样式,请将其放入Container
(又一个和flutter中同样的控件)
Container
: 一个通用的内容对象,用于保存和安排其余UI元素。而后,你能够将大小和位置的设置应用于容器。@Composable
fun NewsStory() {
// 获取图片
val image = +imageResource(R.mipmap.header)
Column (
crossAxisSize = LayoutSize.Expand,
modifier = Spacing(16.dp)
){ // 添加Column,使布局垂直排列
// 放在容器中,设置大小
Container(expanded = true, height = 180.dp) {
// 显示图片
DrawImage(image)
}
Text("我超❤️JetPack Compose的!")
Text("Android技术杂货铺")
Text("依然范特西")
}
}
复制代码
expanded :
指定Container的大小,默认是false
(Container的大小是子组件的大小,至关于wrap_content
),若是将它设置为true
,就指定Container的大小为父控件所容许的最大size, 至关于match_parent
。
height :
设置Container容器的高度,height
属性的优先级高于expanded
,所以会覆盖expanded
,如上面的例子,设置height
为180dp
,也就是容器宽为父控件宽度,高为180dp
Spacer
咱们看到,图片和文本之间没有间距,传统布局中,咱们能够添加Margin
属性,设置间距,在Jetpack Compose 中,咱们可使用HeightSpacer()
和WidthSpacer()
来设置垂直和水平间距
HeightSpacer(height = 20.dp) //设置垂直间距20dp
WidthSpacer(width = 20.dp) // 设置水平间距20dp
复制代码
在上面的例子中,咱们来为图片和文本之间添加20dp
的间距:
@Composable
fun NewsStory() {
// 获取图片
val image = +imageResource(R.mipmap.header)
Column (
crossAxisSize = LayoutSize.Expand,
modifier = Spacing(16.dp)
){ // 添加Column,使布局垂直排列
// 放在容器中,设置大小
Container(expanded = true, height = 180.dp) {
// 显示图片
DrawImage(image)
}
HeightSpacer(height = 20.dp) // 添加垂直方向间距20dp
Text("我超❤️JetPack Compose的!")
Text("Android技术杂货铺")
Text("依然范特西")
}
}
复制代码
Compose 旨在支持Material Design 设计原则,许多组件都实现了Material Design 设计,能够开箱即用,在这一节中,将使用一些Material小组件来对app进行样式设置
Shape
样式Shape
是Material Design 系统中的支柱之一,咱们来用clip
函数对图片进行圆角裁剪。
@Composable
fun NewsStory() {
// 获取图片
val image = +imageResource(R.mipmap.header)
Column (
crossAxisSize = LayoutSize.Expand,
modifier = Spacing(16.dp)
){ // 添加Column,使布局垂直排列
// 放在容器中,设置大小
Container(expanded = true, height = 180.dp) {
Clip(shape = RoundedCornerShape(10.dp)) {
// 显示图片
DrawImage(image)
}
}
HeightSpacer(height = 20.dp) // 添加垂直方向间距20dp
Text("我超❤️JetPack Compose的!")
Text("Android技术杂货铺")
Text("依然范特西")
}
}
复制代码
形状是不可见的,可是咱们的图片已经被裁剪了成了设置的形状样式,所以如上图,图片已经有圆角了。
Text
添加一些样式经过Compose,能够轻松利用Material Design原则。将MaterialTheme()
应用于建立的组件
@Composable
fun NewsStory() {
// 获取图片
val image = +imageResource(R.mipmap.header)
// 使用Material Design 设计
MaterialTheme() {
Column (
crossAxisSize = LayoutSize.Expand,
modifier = Spacing(16.dp)
){ // 添加Column,使布局垂直排列
// 放在容器中,设置大小
Container(expanded = true, height = 180.dp) {
Clip(shape = RoundedCornerShape(10.dp)) {
// 显示图片
DrawImage(image)
}
}
HeightSpacer(height = 20.dp) // 添加垂直方向间距20dp
Text("我超❤️JetPack Compose的!")
Text("Android技术杂货铺")
Text("依然范特西")
}
}
}
复制代码
如上面的代码,添加了MaterialTheme
后,从新运行,效果没有任何变化,文本如今使用了MaterialTheme的默认文本样式。接下来,咱们将特定的段落样式应用于每一个文本元素。
@Composable
fun NewsStory() {
// 获取图片
val image = +imageResource(R.mipmap.header)
// 使用Material Design 设计
MaterialTheme() {
Column (
crossAxisSize = LayoutSize.Expand,
modifier = Spacing(16.dp)
){ // 添加Column,使布局垂直排列
// 放在容器中,设置大小
Container(expanded = true, height = 180.dp) {
Clip(shape = RoundedCornerShape(10.dp)) {
// 显示图片
DrawImage(image)
}
}
HeightSpacer(height = 20.dp) // 添加垂直方向间距20dp
Text("我超❤️JetPack Compose的!", style = +themeTextStyle { h5 }) // 注意添加了style
Text("Android技术杂货铺", style = +themeTextStyle { body1 }) // 注意添加了style
Text("依然范特西", style = +themeTextStyle { body2 }) // 注意添加了style
}
}
}
复制代码
如今看看,咱们的文本样式已经有变化了,标题有6中样式 h1-h6
,其实HTML
中的样式很像,内容文本有body1
和body2
2中样式。
Material 调色版使用了一些基本颜色,若是要强调文本,能够调整文本的不透明度
:
Text("我超❤️JetPack Compose的!", style = (+themeTextStyle { h5 }).withOpacity(0.87f))
Text("Android技术杂货铺", style = (+themeTextStyle { body1 }).withOpacity(0.87f))
Text("依然范特西", style = (+themeTextStyle { body2 }).withOpacity(0.6f))
复制代码
有些时候,标题很长,可是咱们又不想长标题换行从而影响咱们的app UI ,所以,咱们能够设置文本的最大显示行数
,超过部分就截断。
如本例所示,咱们设置显示最大行数为2
,多于的部分截断处理:
Text("我超❤️JetPack Compose的!写起来简单,复用性又强,能够抽取不少组件来复用,不用管理复杂的状态变动!",
maxLines = 2, overflow = TextOverflow.Ellipsis,
style = (+themeTextStyle { h5 }).withOpacity(0.87f))
复制代码
maxLines
和
overflow
以后,超出部分就截断处理了,不会影响到整个布局样式。
从Android Studio 4.0 开始,提供了在IDE中预览composable
函数的功能,不用像之前那样,要先下载一个模拟器,而后将app状态模拟器上,运行app才能看到效果。
可是有一个限制,那就是composable函数不能有参数
知足下面两个条件:
@Preview
注解预览效果图以下:
当布局改变了以后,顶部会出现一个导航条,显示预览已通过期,点击build&Refresh
就能够刷新预览
这真的是一个很是棒的功能,像其余声明式布局,如React 、flutter 是没有这个功能的,布局了以后,要从新运行才能看到效果,虽然能够热启动,可是仍是没有这个预览来得直接。
还有一个很是牛逼的地方是,compose 的预览能够同时预览多个composable
函数。
效果以下:
Jetpack Compse 目前仍是试验版
,因此确定还存在不少问题,还不能如今将其用于商业项目中,可是这并不能妨碍咱们学习和体验它,声明式 UI 框架近年来飞速发展,React 为声明式 UI 奠基了坚实基础并。 Flutter 的发布将声明式 UI 的思想成功带到移动端开发领域,Apple和Google 分别前后发布了本身的声明式UI框架SwiftUI 和 Jetpack Compose , 之后,原生UI布局,声明式可能将会是主流。
以上就是本文的全部内容,但愿它对你有用!
若是你喜欢个人文章,就关注下个人公众号 Android技术杂货铺 、 简书 或者Github! 微信公众号:Android技术杂货铺
简书:www.jianshu.com/u/35167a70a…
GitHub:github.com/pinguo-zhou…