Jetpack (七)Android Compose 基礎(chǔ)<3>

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)
        }
    }
}
  
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載萤皂,如需轉(zhuǎn)載請(qǐng)通過簡信或評(píng)論聯(lián)系作者。
  • 序言:七十年代末匣椰,一起剝皮案震驚了整個(gè)濱河市裆熙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌禽笑,老刑警劉巖入录,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異佳镜,居然都是意外死亡僚稿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門蟀伸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚀同,“玉大人,你說我怎么就攤上這事啊掏〈缆纾” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵迟蜜,是天一觀的道長刹孔。 經(jīng)常有香客問我,道長小泉,這世上最難降的妖魔是什么芦疏? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮微姊,結(jié)果婚禮上酸茴,老公的妹妹穿的比我還像新娘。我一直安慰自己兢交,他們只是感情好薪捍,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著配喳,像睡著了一般酪穿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晴裹,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天被济,我揣著相機(jī)與錄音,去河邊找鬼涧团。 笑死只磷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泌绣。 我是一名探鬼主播钮追,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼阿迈!你這毒婦竟也來了元媚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤苗沧,失蹤者是張志新(化名)和其女友劉穎刊棕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崎页,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鞠绰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了飒焦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜈膨。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖牺荠,靈堂內(nèi)的尸體忽然破棺而出翁巍,到底是詐尸還是另有隱情,我是刑警寧澤休雌,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布灶壶,位于F島的核電站,受9級(jí)特大地震影響杈曲,放射性物質(zhì)發(fā)生泄漏驰凛。R本人自食惡果不足惜胸懈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恰响。 院中可真熱鬧趣钱,春花似錦、人聲如沸胚宦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枢劝。三九已至井联,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間您旁,已是汗流浹背烙常。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留被冒,地道東北人军掂。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像昨悼,于是被迫代替她去往敵國和親蝗锥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容