前言
在本章節(jié)中囱桨,我們將學(xué)習(xí) Jetpack Compose万哪,這是一個用于構(gòu)建原生 UI 的現(xiàn)代工具包偏化。
通過這個完整的教程脐恩,我們將學(xué)習(xí)如何使用 Text、TextField侦讨、Preview驶冒、Column、Row韵卤、Button骗污、Card、AlertDialog沈条、MaterialDesign 元素等需忿。因此,事不宜遲蜡歹,讓我們開始創(chuàng)建一個 Jetpack Compose 項目屋厘。因此,本章節(jié)是關(guān)于通過示例學(xué)習(xí)適用于 Android 的 Jetpack Compose月而。
注意:要使用 Jetpack Compose汗洒,您需要擁有最新的 Canary 版本的 Android Studio 4.2。因此父款,您可以轉(zhuǎn)到Android Studio 預(yù)覽頁面并下載最新的 Canary 版本溢谤,然后創(chuàng)建一個 Empty Compose Activity。
可組合函數(shù)
在 Jetpack Compose 中憨攒,可組合函數(shù)用于以編程方式定義應(yīng)用程序的所有 UI世杀。因此,您無需為應(yīng)用程序的布局使用任何 XML 文件肝集。制作可組合函數(shù)所需要做的就是使用@Composable函數(shù)名稱的注釋玫坛。可組合函數(shù)的基本語法是:
@Composable
fun AnyUiComponent() {
// Code for UI element
}
現(xiàn)在包晰,您知道了可組合函數(shù)是什么以及如何使用@Composable注解創(chuàng)建可組合函數(shù)湿镀。讓我們繼續(xù)看Text的例子。
顯示簡單文本
在本章的這一部分中伐憾,我們將學(xué)習(xí)如何使用 compose 顯示簡單的文本勉痴。
要顯示文本,我們使用 Text Composable 并在其中傳遞要顯示的字符串树肃。例如蒸矛,
@Composable
fun SimpleText(displayText: String) {
Text(text = displayText)
}
在這里,SimpleText是一個可組合函數(shù)胸嘴,在該函數(shù)內(nèi)部雏掠,我們正在使用Text并傳遞displayText給它。
現(xiàn)在劣像,您可以從活動方法的塊中調(diào)用此SimpleText函數(shù)乡话。setContentonCreate
class SimpleTextActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
SimpleText(getString("I am learning Compose"))
}
}
}
}
在這里,我們使用一個Column用于垂直顯示某些內(nèi)容的 Column耳奕,我們正在調(diào)用SimpleTextComposable 函數(shù)绑青。
將樣式應(yīng)用于文本
我們可以將各種樣式應(yīng)用于文本,例如增加字體大小屋群、更改顏色等闸婴。
因此,讓我們創(chuàng)建一個名為 的函數(shù)SetTextStyling:
@Composable
fun SetTextStyling(displayText: String, style: TextStyle? = null, maxLines: Int? = null) {
Text(
text = displayText,
modifier = Modifier.padding(16.dp),
style = style ?: TextStyle.Default,
overflow = TextOverflow.Ellipsis,
maxLines = maxLines ?: Int.MAX_VALUE
)
}
在上面的函數(shù)中芍躏,參數(shù)是displayText即要顯示的文本邪乍,style即要放在Text 上的樣式,maxLines即文本允許的最大行數(shù)对竣。如果文本超過最大行庇楞,則將顯示省略號(...)。
我們將通過傳遞這些參數(shù)來調(diào)用這個函數(shù)柏肪。讓我們看看其中的一些:
- 設(shè)置字體大薪愕蟆:
style = TextStyle(
fontSize = 24.sp
)
- 要設(shè)置字體粗細(xì),請將 text-style 傳遞為:
fontWeight = FontWeight.Bold
同樣烦味,您可以更改字體大小聂使、文本顏色、字體系列谬俄、下劃線文本等柏靶。您可以從我們的開源項目中看到所有這些。
使用 TextField 進(jìn)行輸入
就像 EditText 一樣溃论,在 Compose 中我們可以使用TextField和BaseTextField屎蜓。BaseTextField仍處于試驗階段,可以隨時刪除或永久添加钥勋。因此炬转,要使用BaseTextField辆苔,您需要添加@ExperimentalFoundationApi注釋。
下面是一個簡單的例子BaseTextField:
@ExperimentalFoundationApi
@Composable
fun SimpleTextFieldComponent() {
Surface(color = Color.LightGray, modifier = Modifier.padding(16.dp)) {
var text by remember { mutableStateOf(TextFieldValue("Enter text here")) }
BaseTextField(
value = text,
modifier = Modifier.padding(16.dp).fillMaxWidth(),
onValueChange = {
text = it
}
)
}
}
在上面的函數(shù)中扼劈,我們有一個BaseTextFieldinside a Surface驻啤。我們有一個名為 的回調(diào)onValueChange。當(dāng) 的輸入發(fā)生一些變化時調(diào)用此回調(diào)荐吵,BaseTextField并且更新的文本將作為回調(diào)的參數(shù)出現(xiàn)骑冗。
這是一個例子BaseTextField。Material Design 還為 EditText 提供了一個 Composable先煎,即TextField. 一個簡單的實現(xiàn)TextField如下:
@Composable
fun SimpleMaterialTextFieldComponent() {
var text by savedInstanceState { "" }
TextField(
value = text,
modifier = Modifier.padding(16.dp).fillMaxWidth(),
onValueChange = { text = it },
label = { Text("Label") }
)
}
TextField的行為類似于BaseTextField贼涩。在這里TextField,你還有一件事薯蝎,即label遥倦。標(biāo)簽是在TextField中沒有文本時顯示在 中的文本TextField。
我們可以通過向它傳遞各種參數(shù)來自定義這個 BaseTextField 和 TextField良风。例如谊迄,
- 僅顯示數(shù)字鍵盤:
var text by remember { mutableStateOf(TextFieldValue("0123")) }
BaseTextField(value = text,
keyboardType = KeyboardType.Number,
onValueChange = {
text = it
}
)
- 將密碼作為輸入:
keyboardType = KeyboardType.Password,
visualTransformation = PasswordVisualTransformation()
- 在 TextField 中添加占位符(當(dāng) TextField 為空且有焦點時顯示)
placeholder = { Text("MindOrks") }
同樣,我們可以添加圖標(biāo)烟央,在 TextFiled 中顯示錯誤消息统诺,設(shè)置 errorColor、backgroundColor疑俭、intractionState粮呢、activeColor、inactiveColor 等钞艇。您可以在我們的開源項目中找到這些啄寡。
您可以嘗試這些并在 Android Studio 本身中查看輸出。是的哩照,你沒聽錯挺物。您可以在 Android Studion 本身中預(yù)覽任何 UI 元素。讓我們看看如何飘弧。
在 Android Studio 中預(yù)覽
Android Studio 提供了一個很棒的功能识藤,可以在工作室本身中預(yù)覽您的 UI 組件,而且非常動態(tài)次伶。因此痴昧,每當(dāng)您想測試一些 UI 組件時,您都可以通過制作 Composable 函數(shù)并使用@Preview注解在 Android Studio 中簡單地預(yù)覽它冠王。
以下是相同的示例:
// This is a Composable function to display a Text
@Composable
fun SimpleText(displayText: String) {
Text(text = displayText)
}
@Preview
@Composable
fun SimpleTextPreview() {
SimpleText("Hi I am learning Compose")
}
現(xiàn)在赶撰,在預(yù)覽選項卡(Studio 的右側(cè))中,您可以看到上述 Composable 函數(shù)的預(yù)覽。
您可以使用不同寬度和高度的任意數(shù)量的預(yù)覽豪娜。如果您單擊預(yù)覽中的任何 UI 元素餐胀,Android Studio 會將您帶到創(chuàng)建該 UI 的行。
此外瘤载,您可以使用參數(shù)將一些名稱放入預(yù)覽中name骂澄。要命名預(yù)覽,您需要添加以下代碼:
@Preview(name = "Named Preview")
默認(rèn)情況下惕虑,預(yù)覽的名稱是函數(shù)的名稱。
注意:您不能將任何參數(shù)傳遞給 Preview Composable 函數(shù)磨镶。
預(yù)覽參數(shù)
在上一節(jié)中溃蔫,我們學(xué)習(xí)了如何使用 Android Studio 的預(yù)覽功能。現(xiàn)在琳猫,當(dāng)我們制作任何 Android 應(yīng)用程序時伟叛,在大多數(shù)情況下,數(shù)據(jù)都來自服務(wù)器脐嫂,我們將這些數(shù)據(jù)填充到我們的應(yīng)用程序中统刮。因此,下一個問題是如何預(yù)覽數(shù)據(jù)來自服務(wù)器的 UI账千,即侥蒙,其數(shù)據(jù)現(xiàn)在不可用。對于這些情況匀奏,我們可以使用@PreviewParameter注解鞭衩。
主要思想是制作一個虛擬數(shù)據(jù)并將該虛擬數(shù)據(jù)傳遞給預(yù)覽可組合函數(shù)。由于您不能將任何參數(shù)傳遞給 Preview Composable Function娃善,因此為了實現(xiàn)這一點论衍,您需要使用@PreviewParamter注解來傳遞參數(shù)。
所以聚磺,讓我們首先創(chuàng)建一個虛擬數(shù)據(jù)類坯台。
創(chuàng)建一個名為的數(shù)據(jù)類Blog.kt并將以下代碼添加到其中:
data class Blog(
val name: String,
val author: String
)
現(xiàn)在,創(chuàng)建一個名為的類DummyBlogProvider瘫寝,它實現(xiàn)了一個名為 的接口PreviewParameterProvider:
class DummyBlogProvider : PreviewParameterProvider<Blog> {
override val values =
sequenceOf(Blog("Learning Compose", "MindOrks"), Blog("Learning Android", "MindOrks"))
override val count: Int = values.count()
}
現(xiàn)在蜒蕾,我們完成了虛擬數(shù)據(jù),我們可以在預(yù)覽中使用這個虛擬數(shù)據(jù)矢沿。以下是相同的示例:
@Preview
@Composable
fun BlogInfo(@PreviewParameter(DummyBlogProvider::class) blog: Blog) {
SimpleTextComponent("${blog.name} by ${blog.author}")
}
您可以使用虛擬數(shù)據(jù)查看 UI 的預(yù)覽滥搭。
Column
AColumn是一種可組合的布局,用于將其所有子級一個接一個地垂直放置捣鲸。它類似于具有垂直方向的 LinearLayout瑟匆。
以下是列的示例:
@Composable
fun SimpleColumnComponent() {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = "Hello! I am Text 1", color = Color.Black)
Text(text = "Hello! I am Text 2", color = Color.Blue)
}
}
Scrollable Column
當(dāng)您使用 simpleColumn時,您只能使用手機屏幕的高度。但是愁溜,如果您的內(nèi)容超出了屏幕范圍疾嗅,那么您可以使用ScrollableColumn. ScrollableColumn 就像 ScrollView。
以下是相同的示例:
@Composable
fun ScrollableColumnComponent(blogList: List<Blog>) {
ScrollableColumn {
val context = ContextAmbient.current
Column {
for (blog in blogList) {
Card(
shape = RoundedCornerShape(4.dp),
modifier = Modifier.fillMaxWidth().padding(16.dp).clickable(onClick = {
Toast.makeText(context, "Author: ${blog.author}", Toast.LENGTH_SHORT).show()
}),
backgroundColor = Color(0xFFFFA867.toInt())
) {
Text(
blog.name, style = TextStyle(
fontSize = 16.sp,
textAlign = TextAlign.Center
), modifier = Modifier.padding(16.dp)
)
}
}
}
}
}
Lazy Column
ScrollableColumn在開始時加載其所有元素冕象。例如代承,如果您有 50 個元素,并且在任何時間點屏幕只能顯示 10 個元素渐扮,并且您需要滾動才能看到另一個元素论悴,那么如果您使用的是 a ScrollableColumn,那么最初將加載所有元素墓律。
但是膀估,如果您使用的是LazyColumnFor,那么它將僅加載當(dāng)前在移動屏幕上可見的那些元素耻讽。它的行為有點類似于RecyclerView.
以下是相同的示例:
@Composable
fun LazyColumnScrollableComponent(blogList: List<Blog>) {
LazyColumnFor(items = blogList, modifier = Modifier.fillMaxHeight()) { blog ->
val context = ContextAmbient.current
Card(
shape = RoundedCornerShape(4.dp),
modifier = Modifier.fillParentMaxWidth().padding(16.dp).clickable(onClick = {
Toast.makeText(context, "Author: ${blog.author}", Toast.LENGTH_SHORT).show()
}),
backgroundColor = Color(0xFFFFA867.toInt())
) {
Text(
blog.name, style = TextStyle(
fontSize = 16.sp,
textAlign = TextAlign.Center
), modifier = Modifier.padding(16.dp)
)
}
}
}
現(xiàn)在察纯,如果要水平顯示內(nèi)容,則可以使用 Row针肥、ScrollableRow 或 Lazy Row饼记。所有這些的工作方式分別類似于 Column、ScrollableColumn 和 Lazy Column慰枕。因此具则,為了使此博客提供更多信息,我們不包括該部分捺僻。不過乡洼,您可以從我們的開源項目中找到這些代碼。
Box
Box 是一種可組合的布局匕坯,用于相對于其邊緣放置子級束昵。最初,Stack 被用來代替 Box葛峻。但是現(xiàn)在锹雏,不推薦使用 Stack 并引入了 Box。
顧名思義术奖,孩子被放置在父母內(nèi)部礁遵。框內(nèi)的子元素按指定的順序繪制采记,如果子元素小于父元素佣耐,則默認(rèn)根據(jù)對齊方式將它們放置在框內(nèi)。
以下是 Box 的示例:
@Composable
fun SimpleBoxComponent() {
Box(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Image(imageResource(R.drawable.mindorks_cover))
Text(
modifier = Modifier.padding(start = 16.dp, top = 16.dp),
text = "I am a text over Image",
fontSize = 16.sp,
color = Color.Red
)
}
}
Button
Button用于在用戶單擊時執(zhí)行某些操作唧龄。
以下是一個簡單Button的示例:
@Composable
fun SimpleButtonComponent() {
val context = ContextAmbient.current
Button(
onClick = {
Toast.makeText(context, "Thanks for clicking!", Toast.LENGTH_LONG).show()
},
modifier = Modifier.padding(8.dp).fillMaxWidth()
) {
Text("Click Me")
}
}
這里兼砖,Text用于在按鈕上放置一些文本,onClick回調(diào)用于監(jiān)聽按鈕的點擊事件。
通過將各種參數(shù)傳遞給 Button讽挟,您可以在很大程度上對其進(jìn)行自定義懒叛。其中一些是:
- 制作圓角Button:
shape = RoundedCornerShape(12.dp)
- 制作一個帶邊框的Button:
border = BorderStroke(width = 1.dp, brush = SolidColor(Color.Green))
類似地,您可以為按鈕添加一些圖標(biāo)耽梅、為按鈕應(yīng)用顏色薛窥、禁用按鈕、制作輪廓按鈕眼姐、制作 IconButton诅迷、制作 FAB 等。您可以查看我們的開源項目以獲取更多示例众旗。
Card
Card 是一種可組合的布局竟贯,用于制作 CardView。
以下是相同的示例:
@Composable
fun SimpleCardComponent() {
Card(
backgroundColor = Color(0xFFFFA867.toInt()),
modifier = Modifier.padding(16.dp).fillMaxWidth()
) {
Text(
text = "Simple Card",
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 16.sp
),
modifier = Modifier.padding(16.dp)
)
}
}
Clickable
您可以使用 Clickable 對用戶做出可組合的反應(yīng)逝钥。Clickable 支持單次點擊、雙擊和長按拱镐。
以下是相同的示例:
@Composable
fun SimpleTextComponent() {
val context = ContextAmbient.current
Text(
text = "Click Me",
textAlign = TextAlign.Center,
color = Color.Black,
modifier = Modifier.padding(16.dp).fillMaxWidth().clickable(onClick = {
Toast.makeText(context, "Thanks for clicking! I am Text", Toast.LENGTH_SHORT).show()
}, onLongClick = {
Toast.makeText(context, "Thanks for LONG click! I am Text", Toast.LENGTH_SHORT).show()
}, onDoubleClick = {
Toast.makeText(context, "Thanks for DOUBLE click! I am Text", Toast.LENGTH_SHORT).show()
})
)
}
同樣艘款,您可以使卡片可點擊。
Image
要顯示圖像沃琅,我們可以使用Image可組合的哗咆。
@Composable
fun SimpleImageComponent() {
// Image is a composable that is used to display some image.
val image = imageResource(R.drawable.mindorks_cover)
Column(
modifier = Modifier.padding(16.dp)
) {
Image(image)
}
}
您還可以使用以下代碼制作圓角圖像:
Image(
image,
modifier = Modifier.fillMaxWidth().clip(shape = RoundedCornerShape(8.dp)),
contentScale = ContentScale.Fit
)
Alert Dialog
顧名思義,AlertDialog 用于以對話框的形式向用戶顯示一些重要的消息(可能有一些操作)益眉。
我們在 AlertDialog 中有標(biāo)題晌柬、文本、確認(rèn)按鈕和關(guān)閉按鈕郭脂。
@Composable
fun AlertDialogComponent() {
val openDialog = remember { mutableStateOf(true) }
if (openDialog.value) {
AlertDialog(
onDismissRequest = { openDialog.value = false },
title = { Text(text = "Alert Dialog") },
text = { Text("Hello! I am an Alert Dialog") },
confirmButton = {
TextButton(
onClick = {
openDialog.value = false
/* Do some other action */
}
) {
Text("Confirm")
}
},
dismissButton = {
TextButton(
onClick = {
openDialog.value = false
/* Do some other action */
}
) {
Text("Dismiss")
}
},
backgroundColor = Color.Black,
contentColor = Color.White
)
}
}
Material AppBar
要在 Android 應(yīng)用中顯示 AppBar年碘,您可以在應(yīng)用中使用TopAppBar或BottomAppBar可組合。在這里展鸡,您可以擁有 AppBar 上的標(biāo)題(通常是應(yīng)用程序名稱)屿衅、一些導(dǎo)航圖標(biāo)和一些操作。
@Composable
fun TopAppBarComponent() {
TopAppBar(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
title = { Text("App Name") },
navigationIcon = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Menu)
}
},
actions = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Favorite)
}
IconButton(onClick = { /* doSomething() */ }) {
Icon(Icons.Filled.Favorite)
}
}
)
}
同樣莹弊,我們可以使用BottomAppBar也涤久。
Material BottomNavigation
BottomNavigation 用于在屏幕底部顯示應(yīng)用程序的一些重要操作,以便用戶輕松訪問忍弛。要將項目添加到 a BottomNavigation响迂,我們需要使用BottomNavigationItem可組合項雏搂。
@Composable
fun BottomNavigationWithLabelComponent() {
var selectedItem by remember { mutableStateOf(0) }
val items = listOf("Home", "Blogs", "Profile")
BottomNavigation(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
backgroundColor = Color.Black,
contentColor = Color.Yellow
) {
items.forEachIndexed { index, item ->
BottomNavigationItem(
label = { Text(text = item) },
icon = { Icon(Icons.Filled.Favorite) },
selected = selectedItem == index,
onClick = { selectedItem = index }
)
}
}
}
要使用不帶標(biāo)簽的底部導(dǎo)航呼胚,您可以alwaysShowLabels = false在BottomNavigationItem.
Material Checkbox
當(dāng)我們有 2 個選項并且用戶可以選擇或取消選擇選項時,使用復(fù)選框旺坠。
@Composable
fun SimpleCheckboxComponent() {
val checkedState = remember { mutableStateOf(true) }
Row {
Checkbox(
checked = checkedState.value,
modifier = Modifier.padding(16.dp),
onCheckedChange = { checkedState.value = it },
)
Text(text = "Checkbox Example", modifier = Modifier.padding(16.dp))
}
}
onCheckedChangecallback 用于標(biāo)識 Checkbox 中的變化。
Material ProgressBar
ProgressBar 用于顯示應(yīng)用程序中正在發(fā)生的一些進(jìn)度幕与。例如挑势,從服務(wù)器下載進(jìn)度或加載數(shù)據(jù)。
我們可以制作一個圓形進(jìn)度條或線性進(jìn)度條啦鸣。
以下是循環(huán)進(jìn)度條的示例:
@Composable
fun SimpleCircularProgressComponent() {
CircularProgressIndicator(
modifier = Modifier.padding(16.dp)
)
}
您還可以使用 設(shè)置進(jìn)度進(jìn)度progress = 0.4f潮饱。
同樣,您可以使用LinearProgressIndicator也诫给。
Material Slider
Slider 用于從一系列值中選擇一些值香拉。例如,您可以通過音量滑塊增加/減少音量中狂,通過亮度滑塊等來增加/減少亮度凫碌。
滑塊可以是線性的,也可以有一些離散值胃榕,即您可以滑動以僅選擇允許的值盛险,例如僅選擇整數(shù)值。
@Composable
fun SimpleSliderComponent() {
var sliderValue by remember { mutableStateOf(0.4f) }
Slider(
value = sliderValue,
modifier = Modifier.padding(8.dp),
onValueChange = { newValue ->
sliderValue = newValue
}
)
Text(
text = "Slider value: $sliderValue",
modifier = Modifier.padding(8.dp)
)
}
同樣勋又,您可以通過將 steps 參數(shù)傳遞給 Slider 來制作階梯滑塊苦掘。
Material Snackbar
Snackbar 用于在屏幕底部顯示一些信息,并放置在所有 UI 元素上楔壤。
@Composable
fun SimpleSnackbarComponent() {
Snackbar(
modifier = Modifier.padding(16.dp),
text = {
Text(text = "I'm a Simple Snackbar")
}
)
}
您還可以使用以下方法向 Snackbar 添加一些操作:
action = {
Text(text = "OK", style = TextStyle(color = Color.Green))
}
Custom View
在 Compose 中鹤啡,我們也可以制作一個 Canvas,在畫布上蹲嚣,我們可以繪制各種形狀递瑰,例如圓形、矩形隙畜、弧形等抖部。
@Composable
fun CustomViewComponent() {
Canvas(modifier = Modifier.fillMaxSize().padding(16.dp)) {
drawRect(
color = Color.Red,
// topLeft is the coordinate of top-left point
topLeft = Offset(0f, 0f),
size = Size(800f, 400f)
)
drawArc(
Color.Gray,
startAngle = 0f,
sweepAngle = 120f,
useCenter = true,
size = Size(600f, 600f),
topLeft = Offset(300f, 300f)
)
}
}
Crossfade動畫
我們也可以在 Compose 中使用動畫。例如议惰,我們可以通過使用 Crossfade Composable 來使用 Crossfade 動畫您朽。
@Composable
fun CrossFadeAnimation() {
val colors = listOf(Color.Red, Color.Green, Color.Blue, Color.Gray)
var current by remember { mutableStateOf(colors[0]) }
Column(modifier = Modifier.fillMaxSize()) {
Crossfade(current = current) { color ->
Box(Modifier.fillMaxSize().clickable(
onClick = {
current = colors.random()
}
).background(color))
Text(
modifier = Modifier.fillMaxSize(),
textAlign = TextAlign.Center,
text = "Click To See"
)
}
}
}
在這里,Box 的顏色將隨著單擊 Box 時的 Crossfade 動畫而改變换淆。
這就是本教程的內(nèi)容哗总。您可以嘗試使用 Jetpack Compose 的許多其他示例。
作者:Admin MindOrks
鏈接:https://blog.mindorks.com/jetpack-compose-tutorial