Jetpack Compose 是用于構(gòu)建原生 Android 界面的新工具包雌澄。Jetpack Compose 使用更少的代碼、強(qiáng)大的工具和直觀的 Kotlin API 簡化并加快了 Android 上的界面開發(fā)颅眶。
在本教程中茬斧,您將使用聲明性的函數(shù)構(gòu)建一個(gè)簡單的界面組件。您無需修改任何 XML 布局,也不需要直接創(chuàng)建界面微件论泛,而只需要調(diào)用 Jetpack Compose 函數(shù)來聲明您想要的元素,Compose 編譯器即會(huì)完成后面的所有工作蛹屿。
1.0 API Surface 功能完整屁奏,但可能包含錯(cuò)誤
之前,簡單用兩篇文章認(rèn)識(shí)了下 Compose 使用错负,接下來拆分知識(shí)點(diǎn)學(xué)習(xí)坟瓢。
1. 可組合函數(shù)
Jetpack Compose 是圍繞可組合函數(shù)構(gòu)建的。這些函數(shù)可讓您以編程方式定義應(yīng)用界面犹撒,只需描述應(yīng)用界面的形狀和數(shù)據(jù)依賴關(guān)系折联,而不必關(guān)注界面的構(gòu)建過程。如需創(chuàng)建可組合函數(shù)油航,只需將 @Composable 注釋添加到函數(shù)名稱中即可崭庸。
添加文本元素 Text("Hello world!")
首先,按照 Jetpack Compose 設(shè)置說明操作谊囚,使用 Empty Compose Activity 模板創(chuàng)建一個(gè)應(yīng)用怕享。默認(rèn)模板已包含一些 Compose 元素,但我們下面要逐步進(jìn)行構(gòu)建镰踏。首先函筋,刪除“Greeting”和“Default Preview”函數(shù),然后從 MainActivity
中刪除 setContent
塊奠伪,將該 Activity 留空跌帐。編譯并運(yùn)行您的空白應(yīng)用。
現(xiàn)在绊率,向空白的 Activity 中添加文本元素谨敛。可以通過定義內(nèi)容塊并調(diào)用 Text()
函數(shù)來實(shí)現(xiàn)此目的滤否。
setContent 塊定義了 Activity 的布局脸狸。我們不使用 XML 文件來定義布局內(nèi)容,而是調(diào)用可組合函數(shù)藐俺。Jetpack Compose 使用自定義 Kotlin 編譯器插件將這些可組合函數(shù)轉(zhuǎn)換為應(yīng)用的界面元素炊甲。例如,Compose 界面庫定義了 Text()
函數(shù)欲芹;您可以調(diào)用該函數(shù)在應(yīng)用中聲明文本元素卿啡。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text("Hello world!")
}
}
}
定義可組合函數(shù)
可組合函數(shù)只能在其他可組合函數(shù)的范圍內(nèi)調(diào)用。要使函數(shù)成為可組合函數(shù)菱父,請(qǐng)?zhí)砑?@Composable 注釋颈娜。如需嘗試此操作剑逃,請(qǐng)定義一個(gè) Greeting() 函數(shù)并向其傳遞一個(gè)名稱,然后該函數(shù)就會(huì)使用該名稱配置文本元素揭鳞。
在 Android Studio 中預(yù)覽函數(shù)
當(dāng)前的 Canary 版 Android Studio 允許您在 IDE 中預(yù)覽可組合函數(shù)炕贵,而無需將應(yīng)用下載到 Android 設(shè)備或模擬器中。主要限制在于野崇,可組合函數(shù)不能接受任何參數(shù)称开。因此,您無法直接預(yù)覽 Greeting()
函數(shù)乓梨,而是需要?jiǎng)?chuàng)建另一個(gè)名為 PreviewGreeting()
的函數(shù)鳖轰,由該函數(shù)使用適當(dāng)?shù)膮?shù)調(diào)用 Greeting()
。請(qǐng)?jiān)?@Composable
上方添加 @Preview
注釋扶镀。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Greeting("Android")
}
}
}
@Composable
fun Greeting(name: String) {
Text (text = "Hello $name!")
}
@Preview
@Composable
fun PreviewGreeting() {
Greeting("Android")
}
重新構(gòu)建您的項(xiàng)目蕴侣。由于新的 previewGreeting() 函數(shù)未在任何位置受到調(diào)用,因此應(yīng)用本身不會(huì)更改臭觉,但 Android Studio 會(huì)添加一個(gè)預(yù)覽窗口昆雀。此窗口會(huì)顯示由標(biāo)有 @Preview 注釋的可組合函數(shù)創(chuàng)建的界面元素的預(yù)覽。任何時(shí)候蝠筑,如需更新預(yù)覽狞膘,請(qǐng)點(diǎn)擊預(yù)覽窗口頂部的刷新按鈕。
2. 布局
從一些文本開始, 會(huì)出現(xiàn)重疊現(xiàn)象
返回到您的 Activity什乙,用新的 NewsStory() 函數(shù)替換 Greeting() 函數(shù)挽封。在本教程的其余部分,您將修改該 NewsStory() 函數(shù)臣镣,并且不會(huì)再更改 Activity 代碼辅愿。
最佳做法是單獨(dú)創(chuàng)建不會(huì)被應(yīng)用調(diào)用的預(yù)覽函數(shù);專門的預(yù)覽函數(shù)可以提高性能忆某,并且有利于以后更輕松地設(shè)置多個(gè)預(yù)覽点待。因此,請(qǐng)創(chuàng)建一個(gè)默認(rèn)預(yù)覽函數(shù)弃舒,該函數(shù)的唯一用途就是調(diào)用 NewsStory() 函數(shù)亦鳞。隨著您按照本教程對(duì) NewsStory() 進(jìn)行更改,預(yù)覽內(nèi)容會(huì)反映您所做的更改棒坏。
這段代碼會(huì)在內(nèi)容視圖中創(chuàng)建三個(gè)文本元素。但是遭笋,由于我們未提供有關(guān)如何排列這三個(gè)文本元素的信息坝冕,因此它們會(huì)相互重疊,使文本無法閱讀瓦呼。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NewsStory()
}
}
}
@Composable
fun NewsStory() {
Text("A day in Shark Fin Cove")
Text("Davenport, California")
Text("December 2018")
}
@Preview
@Composable
fun DefaultPreview() {
NewsStory()
}
使用 Column,解決布局問題
Column 函數(shù)可讓您垂直堆疊元素喂窟。向 NewsStory() 函數(shù)中添加一個(gè) Column测暗。
默認(rèn)設(shè)置會(huì)直接將所有子項(xiàng)逐個(gè)堆疊起來,中間不留間距磨澡。Column 本身位于內(nèi)容視圖的左上角碗啄。
@Composable
fun NewsStory() {
Column {
Text("A day in Shark Fin Cove")
Text("Davenport, California")
Text("December 2018")
}
}
向 Column 中添加樣式設(shè)置
通過將參數(shù)傳遞給 Column 調(diào)用,可以配置 Column 的尺寸和位置稳摄,以及 Column 的子項(xiàng)的排列方式稚字。
該設(shè)置具有以下含義:
modifier:可供您配置布局。本例中使用了一個(gè) Modifier.padding 修飾符厦酬,將 Column 內(nèi)嵌在周圍的視圖中胆描。
@Composable
fun NewsStory() {
Column(
modifier = Modifier.padding(16.dp)
) {
Text("A day in Shark Fin Cove")
Text("Davenport, California")
Text("December 2018")
}
}
添加圖片
我們想在文本上面添加圖片仆嗦。使用資源管理器將這張名為 header
的照片添加到應(yīng)用的可繪制資源训唱。
現(xiàn)在,修改您的 NewsStory()
函數(shù)米愿。您將添加對(duì) Image()
的調(diào)用减噪,以將圖片放入 Column
短绸。“foundation”軟件包中提供了這些可組合項(xiàng)筹裕,您可能需要添加該軟件包醋闭。請(qǐng)參閱 Jetpack Compose 設(shè)置說明。圖片的比例會(huì)有問題饶碘,但沒關(guān)系目尖,您可以在下一步中糾正此問題。
@Composable
fun NewsStory() {
Column(
modifier = Modifier.padding(16.dp)
) {
Image(
painter = painterResource(R.drawable.header),
contentDescription = null
)
Text("A day in Shark Fin Cove")
Text("Davenport, California")
Text("December 2018")
}
}
圖片已添加到布局中扎运,但其尺寸尚未調(diào)整為適當(dāng)大小瑟曲。如需設(shè)置圖片樣式,請(qǐng)將尺寸 Modifier 傳遞給對(duì) Image() 的調(diào)用豪治。
height(180.dp):指定圖片的高度洞拨。
fillMaxWidth():指定圖片的寬度應(yīng)足以填充所屬布局。
您還需要向 Image() 傳遞一個(gè) contentScale 參數(shù):
contentScale = ContentScale.Crop:指定圖片應(yīng)填充 Column 的整個(gè)寬度负拟,并根據(jù)需要剪裁為適當(dāng)?shù)母叨取?/p>
@Composable
fun NewsStory() {
Column(
modifier = Modifier.padding(16.dp)
) {
Image(
painter = painterResource(R.drawable.header),
contentDescription = null,
modifier = Modifier
.height(180.dp)
.fillMaxWidth(),
contentScale = ContentScale.Crop
)
Text("A day in Shark Fin Cove")
Text("Davenport, California")
Text("December 2018")
}
}
添加 Spacer烦衣,將圖片與標(biāo)題分開。
@Composable
fun NewsStory() {
Column(
modifier = Modifier.padding(16.dp)
) {
Image(
painter = painterResource(R.drawable.header),
contentDescription = null,
modifier = Modifier
.height(180.dp)
.fillMaxWidth(),
contentScale = ContentScale.Crop
)
Spacer(Modifier.height(16.dp))
Text("A day in Shark Fin Cove")
Text("Davenport, California")
Text("December 2018")
}
}
3. Material Design
Compose 旨在支持 Material Design 原則掩浙。它的許多界面元素都原生支持 Material Design花吟。使用 Material 微件來設(shè)置應(yīng)用的樣式。
采用形狀
Material Design 系統(tǒng)的關(guān)鍵要素之一就是 Shape厨姚。使用 clip() 函數(shù)對(duì)圖片的四角進(jìn)行圓角化處理衅澈。
Shape 不可見,但圖片已被剪裁以匹配 Shape谬墙,因此現(xiàn)在呈現(xiàn)輕微的圓角今布。
設(shè)置文本樣式
借助 Compose经备,您可以輕松遵循 Material Design 原則。將 MaterialTheme 應(yīng)用到您創(chuàng)建的組件部默。
差別可能不太明顯侵蒙,但文本現(xiàn)在采用了 MaterialTheme 的默認(rèn)文本樣式。接下來傅蹂,對(duì)每個(gè)文本元素應(yīng)用特定的段落樣式纷闺。
但有時(shí),一篇文章的標(biāo)題很長贬派,我們不希望過長的標(biāo)題影響應(yīng)用的外觀急但。嘗試更改第一個(gè)文本元素。
配置文本元素搞乏,將長度上限設(shè)置為 2 行波桩。如果文本很短,不超過此限制请敦,則此設(shè)置沒有影響镐躲;但如果文本過長,顯示的文本就會(huì)被自動(dòng)截短侍筛。
@Composable
fun NewsStory() {
MaterialTheme {
val typography = MaterialTheme.typography
Column(
modifier = Modifier.padding(16.dp)
) {
Image(
painter = painterResource(R.drawable.header),
contentDescription = null,
modifier = Modifier
.height(180.dp)
.fillMaxWidth()
.clip(shape = RoundedCornerShape(4.dp)),
contentScale = ContentScale.Crop
)
Spacer(Modifier.height(16.dp))
Text(
"A day wandering through the sandhills " +
"in Shark Fin Cove, and a few of the " +
"sights I saw",
style = typography.h6,
maxLines = 2,
overflow = TextOverflow.Ellipsis)
Text("Davenport, California",
style = typography.body2)
Text("December 2018",
style = typography.body2)
}
}
}