Android Jetpack Compose快速上手
一、Jetpack Compose簡介
Jetpack Compose是Google推出的一個用於構建原生Android 界面的工具包,旨在幫助開發者更快、更輕鬆地在Android 平台上構建原生客户端應用。同時,作為全新的聲明式的UI框架,Jetpack Compose可以使用聲明式Kotlin API取代Android 傳統的xml佈局。
那什麼是聲明式呢?要搞清楚這個問題,我們需要佈局開發中的另外一個概念:命令式。事實上,傳統的使用xml佈局方式就是命令式。在傳統的命令式開發流程中,我們首先需要使用xml來創建佈局,然後再通過findViewById方法獲取控件,最後再綁定數據。而在聲明式開發中,我們可以直接調用compose的庫組件進行渲染,比如:
@Composable
fun ShowText(content: String){
Text(text = content)
}
事實上,除了Jetpack Compose,Flutter、React Native和Swift-UI 等框架都是聲明式的,可以説,前端的大部分的頁面渲染都可以使用聲明式來完成。
二、快速上手
2.1 環境搭建
工欲善其事,必先利其器。目前,Android Studio對Jetpack Compose 已經有了很好的支持,我們只需要下載最新版的Android Studio即可。
安裝完成之後,我們可以下載託管在github上的 Jetpack Compose 示例應用來體驗Jetpack Compose的魅力。
2.2 創建Jetpack Compose應用
為了幫助開發者快速地上手Jetpack Compose,Android Studio提供了支持Jetpack Compose 的新項目模板。我們只需要打開 Android Studio,然後在菜單欄中依次選擇 【File】->【New】->【New Project】 ->【Empty Compose Activity】。
然後,點擊【Next】按鈕,填寫 Name、Package name 和 Save location等參數即可完成Jetpack Compose項目的創建。工程創建完成之後,Jetpack Compose項目會默認添加如下一些依賴。
dependencies {
implementation("androidx.compose.ui:ui:1.2.1")
// Tooling support (Previews, etc.)
implementation("androidx.compose.ui:ui-tooling:1.2.1")
// Foundation (Border, Background, Box, Image, Scroll, shapes, animations, etc.)
implementation("androidx.compose.foundation:foundation:1.2.1")
// Material Design
implementation("androidx.compose.material:material:1.2.1")
// Material design icons
implementation("androidx.compose.material:material-icons-core:1.2.1")
implementation("androidx.compose.material:material-icons-extended:1.2.1")
// Integration with observables
implementation("androidx.compose.runtime:runtime-livedata:1.2.1")
implementation("androidx.compose.runtime:runtime-rxjava2:1.2.1")
// UI Tests
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.2.1")
}
2.3 原有項目添加Jetpack Compose
當然,使用Android Studio提供的Jetpack Compose 模板來創建項目是最簡單的,如果對於老的Android項目,我們需要怎麼處理呢?
首先,打開項目的build.gralde文件,確保Kotlin的版本是1.4.30以上的版本。
plugins {
...
id 'org.jetbrains.kotlin.android' version '1.5.30' apply false
}
然後,打開app/build.gralde文件,添加或修改如下一些配置:
``` android {
// 1、確保最低sdk版本為21或者更高
defaultConfig {
...
minSdkVersion 21
}
buildFeatures {
// 2、開啟 jetpack compose 支持
compose true
}
...
// 3、設置java 和 kotlin 編譯器版本為java8或者更高的版本
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// 4、添加kotlin編譯器擴展版本
composeOptions {
kotlinCompilerExtensionVersion '1.3.0'
}
} ```
然後,添加Jetpack Compose 開發需要的一些依賴庫。
dependencies {
// Integration with activities
implementation 'androidx.activity:activity-compose:1.5.1'
// Compose Material Design
implementation 'androidx.compose.material:material:1.2.1'
// Animations
implementation 'androidx.compose.animation:animation:1.2.1'
// Tooling support (Previews, etc.)
implementation 'androidx.compose.ui:ui-tooling:1.2.1'
// Integration with ViewModels
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1'
// UI Tests
androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.2.1'
}
2.4 遷移到 Compose
對於傳統的xml佈局,我們如何將其遷移到 Jetpack Compose。加入,我們在 XML 佈局中有如下一段代碼。
```
<...>
```
為了將其遷移到 Compose,我們可以將 TextView 替換為保留了相同佈局參數和 id 的 ComposeView,如下所示。
```
<...>
```
然後,在使用了該XML佈局的Activity或Fragment中獲取ComposeView,然後調用setContent方法並向其中添加Compose內容。
```
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
val greeting = findViewById
@Composable private fun Greeting() { Text( text = stringResource(R.string.greeting), style = MaterialTheme.typography.h5, modifier = Modifier .fillMaxWidth() .padding(horizontal = dimensionResource(R.dimen.margin_small)) .wrapContentWidth(Alignment.CenterHorizontally) ) } ```
三、Compose工具
事實上,為了支持Jetpack Compose 的快速開發,Android Studio引入了許多專用於Jetpack Compose 的新功能。它支持使用代碼優先方法,同時提高了開發者的工作效率,因為開發者不必在設計界面或代碼編輯器之間二選一。
而基於View的界面與Jetpack Compose之間的一個基本區別在於,Compose不依賴View來呈現其可組合項。同時,Android Studio 為Jetpack Compose提供了擴展功能,使其不必像 Android View 一樣打開模擬器或連接到設備即可預覽,從而加快了開發者實現其界面設計的迭代過程。
同時,為了實現如需為 Jetpack Compose 的預覽功能,需要我們在應用 build.gradle 文件中添加以下依賴項:
debugImplementation "androidx.compose.ui:ui-tooling:1.2.1"
implementation "androidx.compose.ui:ui-tooling-preview:1.2.1"
3.1 預覽模式
3.1.1 可組合項預覽
首先,我們打開新建的Jetpack Compose項目,MainActivity.kt的代碼如下:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeDemosTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemosTheme {
Greeting("Android")
}
}
在上面的代碼中,setContent()不再是以前的傳遞一個View或者是layout,而是一個組合函數,也就是一個Compose組件。而帶有@Composable的Kotlin函數就是就是一個Compose組件,一般為了跟普通函數區分,因此上面的Greeting和DefaultPreview 都是一個Compose組件。
最後,點擊拆分(設計/代碼)視圖,打開顯示預覽的右側面板就可以看到效果。
@Preview接受參數來支持Android Studio呈現的方式,我們可以在代碼中手動添加這些參數,也可以點擊 @Preview 旁邊的邊線圖標來顯示配置選擇器,以便選擇和更改這些配置參數。
除此之外,Android Studio 提供了一些功能來擴展可組合項預覽。我們可以通過讀取 LocalInspectionMode CompositionLocal來確認可組合項是否正在預覽中呈現。如果可組合項在預覽中呈現,LocalInspectionMode.current 的結果為 true。
if (LocalInspectionMode.current) {
//呈現在預覽界面
Text("Hello preview user!")
} else {
//在App中呈現
Text("Hello $name!")
}
3.1.2 互動模式
互動模式,可以實現在設備上互動的方式和預覽互動,互動模式被隔離在沙盒環境中,在該模式下,我們可以在預覽中點擊元素並輸入用户輸入;預覽甚至播放動畫。預覽互動模式可以直接在Android Studio中運行,由於並未運行模擬器,所以存在一些使用限制:
- 無法訪問網絡
- 無法訪問文件
- 有些 Context API 不一定完全可用
使用互動模式時,只需要編寫好代碼,然後點擊【Start interactive mode】開啟,如下圖。
3.1.3 部署預覽
我們可以使用 @Preview 來部署應用到模擬器或實體設備上。點擊 @Preview 註解旁邊或預覽頂部的 Deploy to Device 圖標 ,Android Studio 會將該 @Preview 部署到連接的設備或模擬器上。
3.1.4 Multipreview
使用 Multipreview註解時,我們可以定義一個註解類,該類本身可配置多個採用不同配置的 Preview註解。將此註解添加到一個可組合函數後,系統會自動同時呈現所有不同的預覽。例如,我們可以定義一個同時支持預覽多個設備、字體大小或主題的註解類。
比如,我們首先定義一個可以改變字體的FontScalePreviews類。
@Preview(
name = "small font",
group = "font scales",
fontScale = 0.5f
)
@Preview(
name = "large font",
group = "font scales",
fontScale = 1.5f
)
annotation class FontScalePreviews
然後,在字體中使用這個預覽可組合項使用此自定義註解。
@FontScalePreviews
@Composable
fun HelloWorldPreview() {
Text("Hello World")
}
最終的效果如下圖。
當然,我們也可以將多個 MultiPreview 註解和普通 preview 註解結合進行使用,從而創建一個更完整的預覽集。結合使用 MultiPreview 註解並不意味着所有不同的組合都會得以呈現。實際上,每個 MultiPreview 註解會獨立運行,並且僅會呈現自己的變體。
@Preview(
name = "dark theme",
group = "themes",
uiMode = UI_MODE_NIGHT_YES
)
@FontScalePreviews
@DevicePreviews
annotation class CombinedPreviews
@CombinedPreviews
@Composable
fun HelloWorldPreview() {
MyTheme { Surface { Text("Hello world") } }
}
通過右鍵點擊呈現的每個預覽,即可將其作為圖像來複制。
默認情況下,我們的可組合項是以透明背景來顯示的。如果需要添加背景,那麼需要用到showBackground 和 backgroundColor 兩個參數,比如:
@Preview(showBackground = true, backgroundColor = 0xFF00FF00)
@Composable
fun WithGreenBackground() {
Text("Hello World")
}
如需手動設置尺寸,可以添加 heightDp 和 widthDp 參數。
@Preview(widthDp = 50, heightDp = 50)
@Composable
fun SquareComposablePreview() {
Box(Modifier.background(Color.Yellow)) {
Text("Hello World")
}
}
有時候,我們需要對狀態欄和操作欄進行一些修改,那麼可以使用showSystemUi參數。
@Preview(showSystemUi = true)
@Composable
fun DecoratedComposablePreview() {
Text("Hello World")
}
當然,我們也可以使用@PreviewParameter註解來添加參數,用來將示例數據傳遞給某個可組合項預覽函數。
@Preview
@Composable
fun UserProfilePreview(
@PreviewParameter(UserPreviewParameterProvider::class) user: User
) {
UserProfile(user)
}
然後,創建一個可實現 PreviewParameterProvider 並以序列形式返回示例數據的類。
class UserPreviewParameterProvider : PreviewParameterProvider<User> {
override val values = sequenceOf(
User("Elise"),
User("Frank"),
User("Julia")
)
}
接着,序列中的每個數據元素都會呈現一個預覽。
當需要為多個預覽使用相同的提供程序類時。如有必要,可通過設置 limit 參數來限制呈現的預覽數量,比如。
@Preview
@Composable
fun UserProfilePreview(
@PreviewParameter(UserPreviewParameterProvider::class, limit = 2) user: User
) {
UserProfile(user)
}
3.2 編輯器
為了提高使用 Jetpack Compose 時的工作效率,Android Studio在編輯器區域提供了一些功能,如實時模板、邊線圖標、顏色選擇器等。
3.2.1 實時模板
Android Studio 提供了Compose 相關的實時模板,開發者可以通過輸入相應的模板縮寫來輸入代碼段,以實現快速插入。
- comp:用於設置 @Composable 函數
- prev:用於創建 @Preview 可組合函數
- paddp:用於以 dp 為單位添加 padding 修飾符
- weight:用於添加 weight 修飾符
- W、WR、WC:用於通過 Box、Row 或 Column 容器設置當前可組合項的呈現效果
3.2.2 邊線圖標
邊線圖標是邊欄中可見的上下文操作,位於行號旁邊。Android Studio 引入了多個 Jetpack Compose 專用邊線圖標,以便開發者更輕鬆地使用。比如,可以直接通過邊線圖標將 @Preview 部署到模擬器或實體設備上。
而對於顏色選擇器來説,我們可以點擊顏色,然後更改選中的眼神,如下所示。
為了方便對圖像進行選擇,Android Studio也支持圖形選擇器,可以通過圖像資源選擇器更改選擇圖片,如下所示:
3.3 迭代開發
作為移動開發者,移動應用界面開發並不是一次性開發完所有的內容的。Android Studio 通過提供不需要完整 build 即可檢查、修改值和驗證最終結果的工具,支持使用 Jetpack Compose 進行逐步開發。
3.3.1 實時修改字面量
Android Studio 可以實時更新在預覽、模擬器和實體設備中的可組合項中使用的一些常量字面量,如Int、String、Color、Dp、Boolean等。
通過“Live Edit of Literals”界面指示器啟用字面量修飾功能,無需進行編譯即可查看觸發實時更新的常量字面量。
3.3.2 實時編輯
我們可以打開 Android Studio Electric Eel 的 Canary 版本,然後使用實時編輯功能加快 Compose 開發過程。相較於實時編輯字面量功能,“實時編輯”是具備更強大功能的版本。開發者可以自動將代碼更改部署到模擬器或設備上,從而實時查看可組合項更新後的效果。
3.3.3 Apply Changes
Apply Changes 支持更新代碼和資源,並且不需要在模擬器或實體設備上重新運行代碼。每當開發者添加、修改或刪除可組合項時,只需要點擊一下此按鈕,即可更新應用,而不必重新部署。
3.4 佈局檢查器
通過佈局檢查器,開發者可以在模擬器或實體設備上檢查正在運行的應用中的 Compose 佈局。
如需跟蹤重組,需要在視圖選項中啟用【Show Recomposition Counts】。
啟用後,佈局檢查器會在左側顯示重組次數,在右側顯示跳過重組的次數。
3.5 動畫
Android Studio 允許開發者從動畫預覽中檢查動畫,我們可以在組合項預覽中描述了動畫效果,檢查每個動畫值在給定時間點的確切值,並且可以暫停、循環播放、快進或放慢動畫,以便在動畫過渡過程中調試動畫。
當然,我們也可以使用動畫預覽以圖形方式呈現動畫曲線,這對於確保正確編排動畫值非常有用。
四、Kotlin與Jetpack Compose配合使用
Jetpack Compose使用Kotlin構建而成,在某些情況下,Kotlin 提供了一些特殊的慣用語,可以幫助開發者編寫良好的 Compose 代碼。如果使用另一種編程語言,那麼很可能會錯失 Compose 的一些優勢。
4.1 默認參數
編寫 Kotlin 函數時,我們可以指定函數參數的默認值;如果調用方未明確傳遞相應的值,系統就會使用這些默認值。在 Kotlin 中,編寫一個函數並指定參數的默認值的方式和Java是類似的。
fun drawSquare(
sideLength: Int,
thickness: Int = 2,
edgeColor: Color = Color.Black
) { ... }
當然,上面的代碼也可以簡寫成下面的方式,Kotlin的編譯器也是可以識別的。
drawSquare(sideLength = 30, thickness = 5, edgeColor = Color.Red)
4.2 高階函數和 lambda 表達式
所謂高階函數,指的是接收其他函數作為參數的函數,Kotlin也是支持高階函數的。例如,Button 可組合函數提供了一個 onClick lambda 參數。
Button(
// ...
onClick = myClickFunction
)
高階函數與 lambda 表達式是自然配對的。如果您只需要使用該函數一次,則不必在其他位置進行定義以將其傳遞給高階函數,而只需使用 lambda 表達式在該位置定義該函數即可。
Button(
// ...
onClick = {
// do something
// do something else
}
) { /* ... */ }
4.3 委託屬性
Kotlin支持委託屬性,這些屬性可以像字段一樣被調用,但它們的值是通過對錶達式動態確定的。
``` class DelegatingClass { var name: String by nameGetterFunction() }
val myDC = DelegatingClass() println("The name property is: " + myDC.name) ```
當執行 println() 函數時,系統會調用 nameGetterFunction() 以返回字符串的值。同時,使用狀態支持的屬性時,這些委託屬性特別有用。
var showDialog by remember { mutableStateOf(false) }
// Updating the var automatically triggers a state change
showDialog = true
4.4 協程
在 Kotlin 中,協程在語言級別提供了異步編程的支持。協程可以掛起執行,而不會阻塞線程。自適應界面本質上是異步的,而 Jetpack Compose 會在 API 級別引入協程而非使用回調來解決此問題。
Jetpack Compose 提供了可在界面層中安全使用協程的 API,rememberCoroutineScope 函數會返回一個 CoroutineScope,可以用它在事件處理腳本中創建協程並調用 Compose Suspend API。
val composableScope = rememberCoroutineScope()
Button(
// ...
onClick = {
composableScope.launch {
scrollState.animateScrollTo(0) // This is a suspend function
viewModel.loadData()
}
}
) { /* ... */ }
默認情況下,協程會依序執行代碼塊。正在運行且調用掛起函數的協程會掛起其執行,直到掛起函數返回,即使掛起函數將執行移至其他 CoroutineDispatcher,也是如此。若要同時執行代碼,則需要創建新的協程。在上述示例中,如需在滾動到屏幕頂部的同時從 viewModel 加載數據,則需要兩個協程。
val composableScope = rememberCoroutineScope()
Button(
onClick = {
composableScope.launch {
scrollState.animateScrollTo(0)
}
composableScope.launch {
viewModel.loadData()
}
}
) { /* ... */ }
協程可幫助您更輕鬆地合併異步 API。在以下示例中,我們會將 pointerInput 修飾符與動畫 API 結合,以便在用户點按屏幕時在元素的位置呈現動畫效果。
@Composable
fun MoveBoxWhereTapped() {
// Creates an `Animatable` to animate Offset and `remember` it.
val animatedOffset = remember {
Animatable(Offset(0f, 0f), Offset.VectorConverter)
}
Box(
// The pointerInput modifier takes a suspend block of code
Modifier.fillMaxSize().pointerInput(Unit) {
// Create a new CoroutineScope to be able to create new
// coroutines inside a suspend function
coroutineScope {
while (true) {
// Wait for the user to tap on the screen
val offset = awaitPointerEventScope {
awaitFirstDown().position
}
// Launch a new coroutine to asynchronously animate to where
// the user tapped on the screen
launch {
// Animate to the pressed position
animatedOffset.animateTo(offset)
}
}
}
}
) {
Text("Tap anywhere", Modifier.align(Alignment.Center))
Box(
Modifier
.offset {
// Use the animated offset as the offset of this Box
IntOffset(
animatedOffset.value.x.roundToInt(),
animatedOffset.value.y.roundToInt()
)
}
.size(40.dp)
.background(Color(0xff3c1361), CircleShape)
)
}
}
- Spring Boot 快速接入 ChatGPT
- 基於OpenAI API構建圖片生成器
- 超詳細的ChatGPT註冊教程來了
- Android桌面圖標快捷方式
- 推薦20個開源的前端低代碼項目
- 輕量級的搜索引擎MeiliSearch
- Android Jetpack Compose快速上手
- Android 13 正式版發佈
- 最新版React Native環境搭建
- 騰訊開源垃圾清理軟件檸檬 Lemon
- RxDogTag:自動標記RxJava原始訂閲點
- 2021,字節最值得關注的10個開源項目
- Google Colab 在線機器學習平台使用教程
- 前端如何開始深度學習,那不妨試試JAX
- 高仿京東Android App,集成React-Native熱更功能
- 一文讀懂Kotlin的數據流
- Android動態更換應用圖標
- HTTP 3規範正式發佈
- 基於Linphone開發Android音視頻通話
- 走進WWDC 2022蘋果開發者大會