1. 事前準備
質感設計是 Google 打造的設計系統,可協助您建構優質的 Android 及其他行動裝置與網路平台數位體驗。這套系統以現實世界及物質紋理為靈感來源,包括物體反映光線和產生陰影的樣態。這套系統提供指南,協助您瞭解如何建構應用程式 UI,使其具備可讀性、吸引力和一致性。
在本程式碼研究室中,您將瞭解可協助您在應用程式中使用質感設計的質感設計主題設定,以及自訂顏色、字體排版和形狀等指引。您可以視需求自訂應用程式,範圍不限。您也將瞭解如何加入頂端應用程式列,以顯示應用程式的名稱和圖示。
必要條件
- 熟悉 Kotlin 語言,包括語法、函式和變數。
- 可在 Compose 中建構版面配置,包括有邊框間距的列和欄。
- 能夠在 Compose 中建立簡單的清單。
課程內容
- 如何在 Compose 應用程式中套用質感設計主題設定。
- 如何在應用程式中加入自訂字型。
- 如何在應用程式中加入自訂調色盤。
- 如何在應用程式的元素中加入自訂形狀。
- 如何在應用程式中加入頂端應用程式列。
建構項目
- 您將建構一個結合質感設計最佳做法的精美應用程式。
軟硬體需求
- 最新版 Android Studio。
- 可下載範例程式碼和字型的網際網路連線。
2. 觀看程式設計示範影片 (可略過)
如果您想觀看課程老師示範完成此程式碼研究室,請觀看以下影片。
建議您在全螢幕模式下觀看影片 (點選影片右下角的 圖示),以便清楚看見 Android Studio 和程式碼。
您可以跳過這個步驟,也可以不觀看這段影片,立即開始進行程式碼研究室的操作步驟。
3. 應用程式總覽
在本程式碼研究室中,您將建立 Woof 應用程式,此應用程式可顯示犬隻清單,然後使用質感設計打造出良好的的應用程式體驗。
我們與設計人員合作設計了 Woof 應用程式,包括選擇應用程式的調色盤、字體排版和形狀。我們知道並非所有人都能存取設計工具,但透過這個程式碼研究室,我們將向您說明使用質感設計主題設定可以完成哪些操作。透過本程式碼研究室,您可以瞭解如何使用質感設計主題設定,改善日後建立的應用程式外觀和風格。
以下是設計人員提供的設計規格,包括淺色主題和深色主題的應用程式視覺設計。
應用程式設計:
淺色主題 | 深色主題 |
調色盤
以下是設計師選擇的淺色和深色主題調色盤。
淺色:
顏色 | 名稱 | 十六進位顏色 | 版位 |
Grey50 | #F8F9FA | primary | |
Green50 | #E6F4EA | surface | |
Green100 | #CEEAD6 | background | |
Grey700 | #5F6368 | secondary | |
Grey900 | #202124 | onSurface | |
Grey900 | #202124 | onPrimary |
深色:
顏色 | 名稱 | 十六進位顏色 | 版位 |
White | #FFFFFF | primary | |
Grey100 | #F1F3F4 | onSurface | |
Grey100 | #F1F3F4 | onPrimary | |
Cyan700 | #129EAF | surface | |
Cyan900 | #007B83 | background | |
Grey900 | #202124 | secondary |
字體排版
以下是設計人員為應用程式選擇的字型。
標題 | 字型 | 字型粗細 | 大小 |
h1 | 一般 | 30sp | |
h2 | 粗體 | 20sp | |
h3 | 粗體 | 14sp | |
body1 | 一般 | 14sp |
主題檔案
Theme.kt 檔案用以存放應用程式主題的所有資訊,檔案包含顏色、字體排版和形狀。在本程式碼研究室中我們只會修改一次,但這是必須要瞭解的重要檔案。檔案內是可組合項 WoofTheme()
,可用於設定應用程式的顏色、字體排版和形狀。
@Composable
fun WoofTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
在 MainActivity.kt 中,加入 WoofTheme()
以提供質感設計主題設定。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
WoofTheme {
WoofApp()
}
}
}
}
看看 DefaultPreview()
。另外也加入了 WoofTheme()
,以在「預覽」分頁標籤中提供顯示的質感設計主題設定。
@Preview
@Composable
fun DefaultPreview() {
WoofTheme(darkTheme = false) {
WoofApp()
}
}
4. 取得範例程式碼
- 前往為專案提供的 GitHub 存放區頁面。
- 按一下「Code」按鈕。系統隨即會開啟對話方塊。
- 在對話方塊中按一下「HTTPS」分頁標籤,然後按一下網址旁的
即可複製網址。請在 Android Studio 中使用此網址。
- 如果 Android Studio 尚未開啟,請開啟 Android Studio,然後在「Welcome to Android Studio」視窗中按一下「Get from VCS」。
- 如果 Android Studio 已開啟,請依序選取「File」>「New」>「Project from Version Control」。
- 在「Get Version Control」視窗的「Version Control」選單中,選取「Git」。
- 在「URL」文字方塊中,輸入您從 GitHub 存放區頁面複製的連結。
- 在「Directory」選單中,選取要從 GitHub 存放區複製原始碼的目錄。
- 按一下「Clone」。
- 等待 Android Studio 下載並開啟專案。
- 在 Android Studio 的導覽選單中,按一下
「Run app」,然後確認應用程式版本可以正常執行。
- 在導覽選單中,按一下「Git」>「Branches...」。
- 在「Remote Branches」區段的「Git Branches」對話方塊中,選取先前提供的分支版本名稱,然後按一下「Checkout」。
- 如需切換分支版本,請依序點選「Git」>「Branches」,然後選取要切換的分支版本,再按一下「Smart Checkout」。
探索範例程式碼
- 在 Android Studio 中開啟範例程式碼。
- 開啟「com.example.woof」>「data」>「Dog.kt」。這包含將用於代表犬隻相片、名稱、年齡和興趣的
Dog data class
。其中也包含犬隻清單,以及要做為應用程式資料使用的資訊。 - 依序開啟「res」>「drawable」。其中包含此專案所需要的所有圖片素材資源,包括應用程式圖示、犬隻圖片和圖示。
- 依序開啟「res」>「values」>「strings.xml」。其中包含在此應用程式中使用的字串,包括應用程式名稱、犬隻名稱和說明等。
- 開啟「MainActivity.kt」。此項目包含建立簡易清單的程式碼,可顯示犬隻相片、犬隻名稱和犬隻年齡。
WoofApp()
包含可顯示DogItems
的LazyColumn
。DogItem()
包含可顯示犬隻相片及其相關資訊的Row
。DogIcon()
可顯示犬隻的相片。DogInformation()
包含犬隻的名稱和年齡。
確保模擬器/裝置採用淺色主題
在這個程式碼研究室中,您將使用淺色和深色兩種主題,但大部分的程式碼研究室都是使用淺色主題。開始設定前,請先確認裝置/模擬器使用淺色主題。
如果要檢視使用淺色主題的應用程式,請在模擬器或實體裝置中執行以下操作:
- 在裝置中前往「Settings」應用程式。
- 搜尋「Dark Theme」,然後按一下以進入。
- 如果已啟用「Dark Theme」,請將其關閉。
執行範例程式碼以瞭解要從什麼地方開始;您要開始操作的地方是顯示犬隻相片、名稱和年齡的清單。這份清單可以正常運作,但並不美觀,所以我們要加以調整。
5. 新增顏色
首先,要在 Woof 應用程式中修改調色盤。
調色盤是應用程式採用的色彩組合。不同的色彩組合會帶來不同的情緒感受,進而影響使用者在使用應用程式時的感受。由於我們和此應用程式的設計師合作,因此他們已經選好了調色盤。不過質感設計網站有提供色彩系統指南,可以協助您進一步瞭解調色盤以及如何自行產生配色。
您之前已經在 Android 應用程式中加入一種顏色,而您使用的是 Color.RED
或 Color.PINK
等。如果要加入更特定的顏色 (例如青藍色或玉綠色),該怎麼做?
在 Android 系統中,色彩會以十六進位色彩值表示。十六進位顏色碼以井字符號 (#) 開頭,後方有六個英文字母及/或數字,代表了顏色的紅、綠、藍 (RGB) 等元件。前兩個字母/數字代表紅色,後兩個代表綠色,後兩個代表藍色。
一個顏色也可以包含一個 Alpha 值 (字母和/或數字),用以表示色彩的透明度 (#00 是不透明度為 0%,也就是完全透明,而 #FF 是不透明度 100%,也就是完全不透明)。加入後,Alpha 值是井字號 (#) 字元後十六進位顏色代碼的前兩個字元。如沒有加入 Alpha 值,系統會假設該值為 #FF,亦即不透明度 100% (完全不透明)。
以下是十六進位顏色值的範例。
顏色 | 名稱 | 十六進位顏色 |
Black | #000000 | |
Green | #72D98C | |
Blue | #4285F4 | |
White | #FFFFFF |
其實您不需要記住顏色的十六進位顏色代碼。我們提供了色彩選取工具,可以協助您產生代表數字。本程式碼研究室有不同顏色可供選擇。
以下是我們在應用程式中使用的調色盤。請注意,應用程式中沒有任何 Alpha 值;也就是說,色彩的透明度為 100%。
淺色:
顏色 | 名稱 | 十六進位顏色 | 版位 |
Grey50 | #F8F9FA | primary | |
Green50 | #E6F4EA | surface | |
Green100 | #CEEAD6 | background | |
Grey700 | #5F6368 | secondary | |
Grey900 | #202124 | onSurface | |
Grey900 | #202124 | onPrimary |
您也許想知道什麼是版位以及指派方式。
- 「Primary」顏色是應用程式畫面和元件最常顯示的顏色。
- 「Secondary」顏色可提供更多強調及區分應用程式的方式。
- 「Surface」顏色會影響元件的表面,例如卡片、工作表和選單。
- 「Background」顏色會顯示在可捲動內容的後方。
- 「On」顏色元素會在調色盤中顯示在其他顏色的「上方」,而且也是套用至文字、圖解和筆觸的主要顏色元素。在調色盤中,我們有「onSurface」顏色 (顯示在「表面」顏色之上),以及「onPrimary」顏色 (顯示在「主要」顏色之上)。
在有連貫邏輯的設計系統中加入這些版位設計,以類似的顏色分類相關的元件。
特定元件會自動對應至顏色版位。舉例來說,Surface
可組合項的 background 顏色會自動對應到 surface 版位。也就是說,您不需要在 Surface
可組合項中明確指派 surface 顏色;在應用程式中設定顏色主題時,這就會自動顯示。實際上我們會有超過六個顏色版位,不過您不需要指派所有版位。任何沒有在應用程式主題中指定的顏色,都會退回至基準質感設計主題 (定義應用程式的預設主題) 中定義的顏色。
現在我們說明了關於顏色的理論,接下來讓我們在應用程式中加入這美麗的調色盤吧!
新增調色盤至主題
- 開啟 Color.kt 檔案。這個檔案用於在應用程式的調色盤中加入新的顏色。現在我們已在對應的預設調色盤中加入了幾種顏色。在已經加入的顏色中,加入這些 Woof 應用程式調色盤所需的新顏色。
//Light Theme
val Grey50 = Color(0xFFF8F9FA)
val Grey900 = Color(0xFF202124)
val Grey700 = Color(0xFF5F6368)
val Green50 = Color(0xFFE6F4EA)
val Green100 = Color(0xFFCEEAD6)
- 開啟 Theme.kt 檔案,然後將
LightColorPalette
替換成下方的程式碼,為其版位加入顏色。
private val LightColorPalette = lightColors(
background = Green100,
surface = Green50,
onSurface = Grey900,
primary = Grey50,
onPrimary = Grey900,
secondary = Grey700
)
WoofTheme()
會檢查 darkTheme
是否設為 True,並將 MaterialTheme
object
中的 colors
設為淺色調色盤 (False) 或深色調色盤 (True)。
@Composable
fun WoofTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
新增顏色至應用程式
現在已經加入了顏色,接下來我們要在應用程式的不同區域使用這些顏色:
- 清單背景 -
background
顏色。 - 清單項目的背景使用
surface
顏色,使其與清單背景顏色有所區分。 - 文字 -
onSurface
顏色 (讓文字在清單項目顏色中更顯眼易讀)。
稍後我們在程式碼研究室中會使用其他兩種顏色。
- 開啟「MainActivity.kt」。在
WoofApp()
中,於LazyColumn
加入背景修飾詞,將清單背景設為綠色。將背景顏色設為在 Theme.kt 中設定的background
顏色。您可以存取透過MaterialTheme.colors.background
設為應用程式主題background
顏色的顏色。 - 在「Preview」分頁標籤中按一下「Build & Refresh」。
import androidx.compose.material.MaterialTheme
import androidx.compose.foundation.background
LazyColumn(modifier =
Modifier.background(MaterialTheme.colors.background))
真厲害!背景現在是 Green100
顏色。
- 在
DogItem()
中,新增background()
副檔名至Row
並傳入MaterialTheme.colors.surface
。這會設定Row
的背景顏色,以使用應用程式主題中指定的surface
顏色。
import androidx.compose.ui.unit.dp
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.background(MaterialTheme.colors.surface)
)
在「Preview」分頁中,您可以看到清單項目的顏色現在與應用程式背景不同,而且每個清單項目也更加不同。
- 在
DogInformation()
中,新增color
至犬隻名稱文字及犬隻年齡文字可組合項。這會變更這兩個文字可組合項的字型顏色。請使用onSurface
顏色。
Column {
Text(
text = stringResource(dog.name),
color = MaterialTheme.colors.onSurface,
modifier = Modifier.padding(top = smallPadding)
)
Text(
text = stringResource(R.string.years_old, dog.age.toString()),
color = MaterialTheme.colors.onSurface
)
}
- 建構與重新整理應用程式。顯示犬隻名稱和年齡的文字與背景的對比度較高,而且更容易閱讀,但在淺色主題中卻較不明顯。
淺色主題:
下方我們可以看到,在深色主題中文字與背景顏色的對比,而我們將在下一節進行實作:
深色主題,沒有文字顏色 | 深色主題,有文字顏色 |
深色主題
在 Android 系統中,您可以選擇將裝置切換為使用深色主題。深色主題使用較深、較柔和的色彩,且:
- 可大幅減少耗電量 (視裝置的螢幕技術而定)。
- 可改善低視能及對明亮光線敏感使用者的可視性。
- 能讓所有人在低光源環境中輕鬆使用裝置。
您的應用程式可以選擇採用強制使用深色設定,讓系統自動採用深色主題。但是對使用者而言,採用深色主題可以帶來更好的體驗,因此建議您不要開放應用程式主題的完整控制選項。
選擇自己的深色主題時,請務必注意深色主題的顏色必須符合無障礙功能對比標準。深色主題會使用色調有限的深色介面顏色。
以下是此應用程式的深色主題顏色:
深色:
顏色 | 名稱 | 十六進位顏色 | 版位 |
White | #FFFFFF | primary | |
Grey100 | #F1F3F4 | onSurface | |
Grey100 | #F1F3F4 | onPrimary | |
Cyan700 | #129EAF | surface | |
Cyan900 | #007B83 | background | |
Grey900 | #202124 | secondary |
新增深色主題
- 在 Color.kt 中加入深色主題的顏色。請注意,由於之前已為淺色主題加入
Grey900
,所以您只需要加入四種顏色。
//Dark Theme
val White = Color(0xFFFFFFFF)
val Grey100 = Color(0xFFF1F3F4)
val Cyan900 = Color(0xFF007B83)
val Cyan700 = Color(0xFF129EAF)
- 移除預設的顏色,因為我們不再需要這些顏色。以下是目前在檔案中的值。
//Light Theme
val Grey50 = Color(0xFFF8F9FA)
val Grey900 = Color(0xFF202124)
val Grey700 = Color(0xFF5F6368)
val Green50 = Color(0xFFE6F4EA)
val Green100 = Color(0xFFCEEAD6)
//Dark Theme
val White = Color(0xFFFFFFFF)
val Grey100 = Color(0xFFF1F3F4)
val Cyan900 = Color(0xFF007B83)
val Cyan700 = Color(0xFF129EAF)
- 將 Theme.kt 檔案中的現有
DarkColorPalette
替換為以下顏色。
private val DarkColorPalette = darkColors(
background = Cyan900,
surface = Cyan700,
onSurface = White,
primary = Grey900,
onPrimary = White,
secondary = Grey100
)
在預覽畫面中檢視深色主題
如要查看深色主題,請在 MainActivity.kt 中新增另一個 Preview()
。這樣一來,在程式碼中變更 UI 版面配置時,就能同時查看淺色主題和深色主題的預覽畫面。
- 在
DefaultPreview()
下方,建立名為DarkThemePreview()
的新函式,並使用@Preview
和@Composable
加上註解。
@Preview
@Composable
fun DarkThemePreview() {
}
- 在
DarkThemePreview()
內加入WoofTheme()
。如果沒有加入WoofTheme()
,就無法查看應用程式新增的任何樣式。將darkTheme
參數設為 True。
@Preview
@Composable
fun DarkThemePreview() {
WoofTheme(darkTheme = true) {
}
}
- 呼叫
WoofTheme()
內的WoofApp()
。
@Preview
@Composable
fun DarkThemePreview() {
WoofTheme(darkTheme = true) {
WoofApp()
}
}
現在,在 Preview
區段中按一下「Build & Refresh」,然後向下捲動,就可以看到使用深色主題的應用程式,包括顏色較深的應用程式/清單項目背景及白色文字。您可以比較深色主題和淺色主題之間的差異。
深色主題 | 淺色主題 |
在裝置或模擬器中檢視深色主題
如要在模擬器或實體裝置中以深色主題檢視應用程式:
- 在裝置中前往「Settings」應用程式。
- 搜尋「Dark Theme」,然後按一下以進入。
- 啟用「Dark Theme」。
- 重新開啟 Woof 應用程式,應用程式將採用深色主題。
本程式碼研究室著重在淺色主題上,因此繼續設計應用程式前,請先停用深色主題。
- 在裝置中前往「Settings」應用程式。
- 選取「Display」。
- 關閉「Dark theme」。
比較本課程一開始與現在的應用程式。清單項目和文字的定義更明確,且色彩配置也更搶眼。
沒有顏色 | 有顏色 (淺色主題) | 有顏色 (深色主題) |
6. 新增形狀
根據預設,應用程式中的所有形狀都是矩形。不過,套用形狀可能會改變可組合項的外觀和風格。形狀可以吸引注意、辨識元件、傳達狀態,並表達品牌概念。
許多形狀都是以描述矩形圓角使用的 RoundedCornerShape
定義。傳入的數值會定義圓角。如果使用 RoundedCornerShape(percent = 0)
,則矩形沒有圓角;如果使用 RoundedCornerShape(percent = 50)
,邊角就會是圓角。如果要設計更複雜的形狀,可以使用質感網站提供的圖形自訂工具。
0% | 25% | 50% |
Shape.kt 檔案是用以在 Compose 中定義元件形狀。元件分為三種:小、中、大。在本節中,您將修改定義 medium
大小的 Card
元件。元件會根據其大小以形狀類別分組。
由於 Image
不是元件,因此您將在 MainActivity.kt 中加入形狀。
在本節中,您要將犬隻的圖片設為圓形,並修改清單項目的形狀。
將犬隻圖片設為圓形
- 首先,年要將犬隻相片的圖示修改成圓形。開啟「MainActivity.kt」。在
DogIcon()
中,在Image
的modifier
中加入clip
屬性,這會將圖片剪輯成一個形狀。傳入RoundedCornerShape()
,然後傳入 50,就可將邊角設為完整的圓形。
import androidx.compose.ui.draw.clip
import androidx.compose.foundation.shape.RoundedCornerShape
@Composable
fun DogIcon(@DrawableRes dogIcon: Int, modifier: Modifier = Modifier) {
Image(
modifier = modifier
.size(64.dp)
.padding(8.dp)
.clip(RoundedCornerShape(50)),
在查看 DefaultPreview
時,犬隻圖示就會顯示為圓形!不過,有些相片會在兩側截斷,因此無法顯示為完整的圓形。
- 如要將所有相片設為圓形,請加入
ContentScale
和Crop
屬性,這樣就可以根據顯示大小裁剪圖片。請注意,contentScale
是Image
的屬性,並不屬於modifier
。
import androidx.compose.ui.layout.ContentScale
@Composable
fun DogIcon(dogIcon: Int, modifier: Modifier = Modifier) {
Image(
modifier = modifier
.size(64.dp)
.padding(8.dp)
.clip(RoundedCornerShape(50)),
contentScale = ContentScale.Crop,
現在當您執行應用程式時,圖示會以圓形顯示。
在清單項目中加入圖案
在本節中,您將在清單項目中加入一個形狀。清單項目已在 Row
中顯示,但 Row
無法設定形狀。所以您要在 Card
中加入 Row
。Card
是只能包含一個可組合項的表面,且包含裝飾選項。您可以透過邊框、形狀、高度等項目加入裝飾。在本節中,您將使用 Card
在清單項目中加入形狀。
- 在
DogItem()
中,在Row
周圍加入Card
。
import androidx.compose.material.Card
@Composable
fun DogItem(dog: Dog, modifier: Modifier = Modifier) {
Card() {
Row(
- 開啟 Shape.kt 檔案。
Card
是中型元件,因此您需要更新Shapes
物件的中型屬性。就這個應用程式而言,您要將清單的邊角設為圓形,但又不要設為完整的圓形。要完成此設定,只要在medium
屬性中傳入16.dp
即可。
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(16.dp),
large = RoundedCornerShape(0.dp)
)
- 由於根據預設,
Card
已使用中型形狀,因此您不必明確地將其設為中型形狀。重新整理「Preview」,即可看到圓角!不過,這些清單項目之間不會有邊框間距,而且也無法確定每個清單項目結束和下一個項目開始的位置。現在,您必須在清單項目之間加入邊框間距,以在每個項目之間建立定義。
如果返回 WoofTheme()
中的 Theme.kt 檔案並查看 MaterialTheme()
,就會發現 shapes
屬性已設為您剛才更新過的 Shapes
val
。
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
更新修飾詞並加入邊框間距
- 由於
Card
現在是DogItem()
中顯示的第一個可組合項,傳遞至DogItem
可組合項的修飾詞應轉至Card
,而不是Row
。Row
現在會使用新的Modifier
執行個體。
@Composable
fun DogItem(dog: Dog, modifier: Modifier = Modifier) {
Card(
modifier = modifier
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.background(MaterialTheme.colors.surface)
)
- 在
Card modifier
中加入padding
,然後傳入8.dp
以在各個清單項目周圍加入邊框間距。
Card(
modifier = modifier.padding(8.dp)
)
現在,只要重新整理「Preview」,有圓角的清單項目就會更清楚顯示,而這是因為每個項目之間有邊框間距。
對比不明顯的顏色
Card
是 Surface
,而在「Theme.kt」檔案中,我們已明確設定了 surface
版位的顏色。因此,我們可以從 Row
移除顏色,且不必將其明確設定為 surface
顏色。
- 在
DogItem()
中移除背景色彩的明確設定。
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
重新整理「Preview」,就會發現即使我們已經移除明確的色彩指定設定,Row
的背景顏色仍然相同。
- 由於犬隻名稱和年齡的
Text
位於Surface
之上,因此其顏色預設為onSurface
。移除DogInformation()
中Text
個項目的明確色彩設定。
以下是可組合項現在的顯示效果:
@Composable
fun DogInformation(@StringRes dogName: Int, dogAge: Int, modifier: Modifier = Modifier) {
Column {
Text(
text = stringResource(dogName),
modifier = modifier.padding(top = 8.dp)
)
Text(
text = stringResource(R.string.years_old, dogAge)
)
}
}
新增清單項目的高度
現在這個應用程式有清單項目形狀,看起來真的很不賴,但是我們還要加入一點額外的設定,讓清單項目與背景之間的對比更強烈。您已使用 Card
shape
屬性設定清單項目的形狀,現在您將使用 Card
elevation
屬性,在資訊卡中加入高度。基本上,高度會加上陰影效果,讓 Card
與背景之間的對比更鮮明,也讓應用程式看起來更生動、讓人印象深刻。
- 在
DogItem()
中,新增list_item_elevation
為Card
的elevation
屬性。
Card(
modifier = Modifier.padding(8.dp),
elevation = 4.dp
)
- 重新整理「Preview」。高度可為應用程式加上陰影和深度,讓應用程式看起來更生動!
下方是應用程式的前後對照圖。您可以注意到,在應用程式中加入形狀後,應用程式在視覺上更具有吸引力。
不使用形狀 | 使用形狀 |
7. 新增字體排版
質感設計輸入比例
輸入比例是可以在應用程式中使用的多種字型樣式,可確保風格靈活、一致。質感設計輸入比例包含 13 種字型系統支援的字型樣式。只有在需要自訂應用程式時才需要使用這些選項。如果您不知道如何設定每個輸入比例類別,別忘了您可以使用預設的字體排版比例。
輸入比例包含可重複使用的類別,每個類別都有對應的應用程式和意義。在我們的應用程式中,我們只會使用標題和內文類別。
標題
在輸入比例中,標題的大小從 1 到 6 都有。標題是畫面中最大的文字,應使用簡短且具重要性的文字或數字。
內文
內文文字的範圍介於 1 到 2 之間,一般用於較長篇幅的內容撰寫,因為這類文字適合使用較小的字體。
字型
Android 平台提供幾種字型,但建議您使用非預設字型以真正自訂應用程式。自訂字型可以為品牌增添個性,也可用於宣傳品牌。
在本節中,您將新增自訂字型,名稱為 Abril Fatface、Montserrat Bold 和 Monterrat Regular。您將使用質感字型系統中的 H1 和 H2 標題和 body1 文字,並將這些文字加入至應用程式中的文字。
建立字型 Android 資源目錄。
在應用程式中加入字型之前,您必須先加入字型目錄。
- 在 Android Studio 的專案檢視畫面中,在「res」資料夾按一下滑鼠右鍵。
- 依序選取「New」>「Android Resource Directory」。
- 將目錄命名為「font」,將資源類型設為「font」,然後按一下「OK」。
- 依序點選「res」>「font」,開啟其中的新字型資源目錄。
下載自訂字型
由於您使用的字型並非 Android 平台提供,因此您必須下載自訂字型。
- 前往 https://fonts.google.com/。
- 搜尋 Montserrat,然後按一下「Download family」。
- 解壓縮 zip 檔案。
- 開啟下載的 Montserrat 資料夾。在 static 資料夾中,找到 Montserrat-Bold.ttf 和 Montserrat-Regular.ttf (ttf 代表 TrueType 字型,也是字型檔案的格式)。選取這兩種字型,然後拖曳至 Android Studio 中的專案字型資源目錄。
- 在字型資料夾中,將 Montserrat-Bold.ttf 重新命名為 montserrat_bold.ttf,並將 Montserrat-Regular.ttf 重新命名為 montserrat_regular.ttf。
- 搜尋 Abril Fatface,然後按一下「Download family」。
- 開啟下載的 Abril_Fatface 資料夾。選取 AbrilFatface-Regular.ttf,然後拖曳至字型資源目錄之中。
- 在字型資料夾中,將 Abril_Fatface.ttf 重新命名為 abril_fatface_regular.ttf。
以下是專案中的字型資源目錄加入三個自訂字型檔案後:
初始化字型
- 在專案視窗中,開啟 ui.theme > Type.kt,然後刪除
Typography
變數的內容。
// Set of Material typography styles to start with
val Typography = Typography(
)
- 在匯入陳述式下方和
Typography
val
上方初始化下載的字型。首先,將 Abril Fatface 設為等於FontFamily
以進行初始化,然後使用字型檔案abril_fatface_regular
傳入Font
。
val AbrilFatface = FontFamily(
Font(R.font.abril_fatface_regular)
)
- 在 Abril Fatface 下初始化 Montserrat (方法是將其設為等於
FontFamily
,然後使用檔案montserrat_regular
傳入Font
)。如果是montserrat_bold
,請加入FontWeight.Bold
。即使傳入字型檔案的粗體版,Compose 也無法辨別檔案為粗體,因此您必須明確連結檔案至FontWeight.Bold
。
val AbrilFatface = FontFamily(
Font(R.font.abril_fatface_regular)
)
val Montserrat = FontFamily(
Font(R.font.montserrat_regular),
Font(R.font.montserrat_bold, FontWeight.Bold)
)
接著,將剛才新增的字型設定不同類型的標題。Typography
物件包含上述 13 個不同字體的參數。您可以定義的數量沒有限制。在此應用程式中,我們將設定 h1
(標題 1)、h2
(標題 2) 和 body1
。在這個應用程式的下一個部分,您要使用 h3
(標題 3),因此請在這裡加入標題。
以下是「應用程式總覽」部分的資料表,可顯示加入的每個標題使用的字型和大小。
標題 | 字型 | 字型粗細 | 大小 |
h1 | 一般 | 30sp | |
h2 | 粗體 | 20sp | |
h3 | 粗體 | 14sp | |
body1 | 一般 | 14sp |
- 依照上表填寫
Typography
val
。請將h1
屬性設為等於TextStyle
,然後使用上表的資訊填入fontFamily
、fontWeight
和fontSize
。這表示所有設為h1
的文字都會使用 Abril Fatface 字型,且字型粗細為一般,fontSize
則為30.sp
。
h2
、h3
和 body1
都要重複此程序。
val Typography = Typography(
h1 = TextStyle(
fontFamily = AbrilFatface,
fontWeight = FontWeight.Normal,
fontSize = 30.sp
),
h2 = TextStyle(
fontFamily = Montserrat,
fontWeight = FontWeight.Bold,
fontSize = 20.sp
),
h3 = TextStyle(
fontFamily = Montserrat,
fontWeight = FontWeight.Bold,
fontSize = 14.sp
),
body1 = TextStyle(
fontFamily = Montserrat,
fontWeight = FontWeight.Normal,
fontSize = 14.sp
)
)
如果返回 WoofTheme()
中的 Theme.kt 檔案並查看 MaterialTheme()
,就會看到 typography
屬性已設為您剛才更新的 Typography
val
。
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
在應用程式文字中新增字體排版
現在,您將在應用程式中的每個文字執行個體中加入標題類型。
- 新增
h2
(標題 2) 為dog name
的樣式,因為這是簡短且重要的資訊。新增body1
為dog age
的樣式,因為這適合使用較小的文字大小。
@Composable
fun DogInformation(@StringRes dogName: Int, dogAge: Int, modifier: Modifier = Modifier) {
Column {
Text(
text = stringResource(dogName),
style = MaterialTheme.typography.h2,
modifier = modifier.padding(top = 8.dp)
)
Text(
text = stringResource(R.string.years_old, dogAge),
style = MaterialTheme.typography.body1
)
}
}
- 重新整理應用程式。現在犬隻名稱會在
20.sp
中以粗體的 Montserrat 字型顯示,而犬隻年齡則會在14.sp
中以一般 Montserrat 字型顯示。
下方是應用程式中加入字體排版的前後對照圖。請注意犬隻名稱與犬隻年齡的字型差異。
沒有字體排版 | 有字體排版 |
8. 新增頂端列
Scaffold
是一種版面配置,可為多個元件和畫面元素提供版位,例如:Image
、Row
或 Column
。Scaffold
也會提供 topBar
的版位,您可以在此部分使用。
topBar
有許多用途,但在這個情況下,您將以此做品牌宣傳使用,也可以讓應用程式更增添特色。您將建立一個可組合項 (如下方螢幕截圖所示),然後將其排入 Scaffold
的 topBar
區段。
對於此應用程式,我們的頂端列由包含標誌和應用程式標題的列組成。標誌裡有可愛的漸層狗爪,還有應用程式標題!
在頂端列中新增圖片和文字
- 在 MainActivity.kt 中,建立接受
modifier
且名為WoofTopAppBar()
的可組合項。
@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier) {
}
- 在
WoofTopAppBar()
中加入Row()
。
@Composable
fun WoofTopAppBar(modifier: Modifier = Modifier) {
Row() {
}
}
- 在
Row
中加入Image
。使用painter
以從可繪項目資料夾設定Image
為ic_woof_logo
,然後將contentDescription
設定為「null」。在這種情況下,應用程式標誌不會為視障使用者加入任何語意資訊,因此我們不必加入內容說明。
Image(
painter = painterResource(R.drawable.ic_woof_logo),
contentDescription = null
)
- 接下來,在
Image
之後於Row
之內加入一個Text
可組合項,然後使用stringResource()
將其設為app_name
的值。這會將文字設定為應用程式的名稱 (儲存在strings.xml
中)。
Text(
text = stringResource(R.string.app_name)
)
- 現在您已在
TopAppBar()
中加入圖示和應用程式名稱,您必須在版面配置中加入TopAppBar()
。在WoofApp()
中,加入包圍LazyColumn
的Scaffold
。
import androidx.compose.material.Scaffold
@Composable
fun WoofApp() {
Scaffold(
) {
LazyColumn(modifier =
Modifier.background(MaterialTheme.colors.background)) {
items(dogs) {
DogItem(dog = it)
}
}
}
}
- 在
Scaffold
中加入topBar
屬性,並將其設為WoofTopAppBar()
。
Scaffold(
topBar = {
WoofTopAppBar()
}
)
以下是 WoofApp()
可組合項的外觀:
@Composable
fun WoofApp() {
Scaffold(
topBar = {
WoofTopAppBar()
}
) {
LazyColumn(modifier = Modifier.background(MaterialTheme.colors.background)) {
items(dogs) {
DogItem(dog = it)
}
}
}
}
- 重新整理「Preview」,然後查看頂端應用程式列。此列會顯示圖示和文字,但這並不是我們要的最終產品。在下一節中,您將使用顏色、字體排版、邊框間距等設計,打造出更美觀的效果。
美化頂端列外觀
- 首先,在頂端列加入背景顏色,讓頂端列與應用程式的其餘部分做出區分。在
WoofTopAppBar()
中,於Row
中加入modifier
,以加入主要應用程式主題顏色做為背景顏色,然後將背景顏色設為primary
。
Row(
modifier = modifier
.background(color = MaterialTheme.colors.primary)
){ }
- 背景顏色只會顯示在圖示和文字的後方,但因為我們要涵蓋整個應用程式的寬度。因此我們要將
Row
上的modifier
設為fillMaxWidth()
。
Row(
modifier = modifier
.fillMaxWidth()
.background(color = MaterialTheme.colors.primary)
){ }
- 接下來,請更新文字以使其符合您先前定義的
h1
(標題 1) 樣式。由於背景設為primary
顏色,因此文字會自動設為onPrimary
顏色。
Text(
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.h1
)
- 這樣看起來好多了,但圖片太小了,而且也可以加上一些邊框間距。在
Image
中新增修飾詞,將圖片大小設為64.dp
,然後將圖片周圍的邊框間距設為8.dp
。
Image(
modifier = Modifier
.size(64.dp)
.padding(8.dp),
painter = painterResource(R.drawable.ic_woof_logo),
contentDescription = null
)
- 快完成了!現在,將垂直對齊方式設為
Alignment.CenterVertically
,該列會逐列列出所有項目。
import androidx.compose.ui.Alignment
Row(
modifier = modifier
.fillMaxWidth()
.background(color = MaterialTheme.colors.primary),
verticalAlignment = Alignment.CenterVertically
){ }
執行應用程式,然後就可以看到 TopAppBar
如何以美觀的方式將應用程式組合在一起。
沒有頂端應用程式列 | 有頂端應用程式列 |
現在,請以深色主題執行應用程式。由於列會使用 primary
顏色,而文字則是使用 onSurface
顏色,因此您不必為更新深色主題。
恭喜,您已經順利完成本篇程式碼研究室課程!
9. [選用] 變更狀態列
如要進一步提升使用者體驗,您可以更新包含時間、網際網路連線、電池狀態等資訊的狀態列顏色。
- 依序前往 app > res > values > colors.xml。
- 刪除
<resources>
標記的內容。
<resources>
</resources>
- 加入
grey_50
,然後將其設為淺色主題狀態列的#FFF8F9FA
,再加入grey_900
,將其設為深色主題狀態列的#FF202124
。
<resources>
<color name="grey_50">#FFF8F9FA</color>
<color name="grey_900">#FF202124</color>
</resources>
- 導覽至 app > res > values > themes.xml,然後以
grey_50
取代android:statusBarColor
中的顏色。
<resources>
<style name="Theme.Woof" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@color/grey_50</item>
</style>
</resources>
- 在裝置或模擬器中執行應用程式。
狀態列現在已和頂端應用程式列相符,色彩配置也更加一致,但現在卻無法看到圖示。
- 在「themes.xml」檔案中加入
windowLightStatusBar
,然後在statusBarColor
將其設為「True」。
<resources>
<style name="Theme.Woof" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@color/grey_50</item>
<item name="android:windowLightStatusBar">true</item>
</style>
</resources>
- 您將收到一則錯誤訊息。將滑鼠游標懸停在該則訊息上,然後按下「Override Resources in values-v23」(覆寫資源值 v23)。
- 這會建立新的 themes.xml 檔案,名稱為 v23/themes.xml,適用於 23 以上的 API 級別。
- 在模擬器中執行應用程式。請注意,您現在可以看到圖示!
新增深色主題狀態列
現在,您可以使用深色主題自訂狀態列。
- 在 res 資料夾中,新增名為 values-night 的 Android 資源目錄。
- 切換至「Project Source Files」(專案來源檔案) 檔案檢視。
- 依序前往 app > src > main > res > values-night。
- 在 values-night 中,加入「值資源檔案」(Values Resource File),名稱為
themes.xml
。 - 新增名稱為
Theme.Woof
的樣式標記,且父項為android:style/Theme.Material.NoActionBar
。
<resources>
<style name="Theme.Woof" parent="android:style/Theme.Material.NoActionBar">
</style>
</resources>
- 新增狀態列顏色為
grey_900
。由於預設是白色圖示,因此您不需要加入windowsStatusLightBar
。
<resources>
<style name="Theme.Woof" parent="android:style/Theme.Material.NoActionBar">
<item name="android:statusBarColor">@color/grey_900</item>
</style>
</resources>
- 以深色主題執行應用程式,以查看狀態列更新。
10. 取得解決方案程式碼
完成程式碼研究室後,如要下載當中用到的程式碼,您可以使用這些 git 指令:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-woof.git $ cd basic-android-kotlin-compose-training-woof $ git checkout material
另外,您也可以下載存放區為 ZIP 檔案,然後解壓縮並在 Android Studio 中開啟。
如要查看解決方案程式碼,請前往 GitHub 檢視。
11. 結語
您剛剛建立了第一個質感應用程式!您加入了淺色和深色主題的自訂調色盤,還為各種元件分別建立圖形、下載字型,並將其新增至應用程式,更建立了精美的頂端列來合併所有項目。請善加運用您在本程式碼研究室所學到的技巧,變更顏色、形狀和字型,打造出您專屬的應用程式!
摘要
- Material Design 主題設定可讓您在應用程式中使用 Material Design,依照指示自訂顏色、字體和形狀。
- 主題是由 Theme.kt 檔案中的可組合項所定義。可組合項的命名方式為 [應用程式名稱]+Theme(),以這個應用程式來說,就是
WoofTheme()
。在這個函式中,MaterialTheme
object
會設定應用程式的color
、typography
、shapes
和content
。 - 您可以在 Colors.kt 中列出應用程式使用的顏色,然後在 Theme.kt 中指派
LightColorPalette
和DarkColorPalette
中的顏色至特定版位。您不需要指派所有版位。 - 您的應用程式可以選擇採用強制使用深色設定,讓系統自動採用深色主題。但是對使用者而言,採用深色主題可以帶來更好的體驗,因此建議您不要開放應用程式主題的完整控制選項。
- Shapes.kt 可讓您定義應用程式形狀。指定圓角的形狀時,您有三種形狀大小可以選擇 (小、中、大)。
- 形狀可以吸引注意、辨識元件、傳達狀態,並表達品牌概念。
- Types.kt 可讓您初始化字型,並為質感設計輸入比例指派
fontFamily
、fontWeight
和fontSize
。 - 質感設計輸入比例包含多種對比樣式,可滿足應用程式及其內容的需求。輸入比例是輸入系統支援的 13 種樣式組合。