在今年的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…