remember
會把物件儲存在 Composition 內,當 recomposition 期間 remember
所在的 scope 沒有再度被呼叫時,則會清除該物件。
此系列文章是以我的業餘專案: Kimoji 作為範例。
這款以純 Jetpack Compose 撰寫的 side project,已經在 Google Play 上架。 歡迎試玩!
立馬下載
為了將這個行為以視覺化呈現,我們要在 app 內實作以下功能:如果使用者今天發了脾氣,就顯示一項可以「緩和情緒的任務」給使用者去做,而使用者也能選擇關閉任務。因為 composables 應該精簡且可供重複使用,我們來建立新的 composable 並命名為 WellnessTaskItem
,讓這個 composable 將收到的 string 當做參數,並按照這個參數顯示「情緒緩和任務」,以及一個「關閉」圖示按鈕。
我們來建立新檔案 WellnessTaskItem.kt
並加入以下程式碼。我們在後續步驟中將會用到這個 composable function。
import androidx.compose.foundation.layout.Row
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.layout.padding
@Composable
fun WellnessTaskItem(
modifier: Modifier = Modifier,
taskName: String,
onClose: () -> Unit
) {
Row(
modifier = modifier, verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier.weight(1f).padding(start = 16.dp),
text = taskName
)
IconButton(onClick = onClose) {
Icon(Icons.Filled.Close, contentDescription = "Close")
}
}
}
WellnessTaskItem
函式會接收「任務名稱」,以及 onClose
lambda 函式做為參數 (就像內建的 Button
composable 接收 onClick
一樣)。
WellnessTaskItem
看起來會像這樣:
接著,我們來實作 AngryCounter
以便在 count > 0
時顯示 WellnessTaskItem
。
當 count
大於 0 時,定義變數 showTask
藉此定義是否要顯示 WellnessTaskItem
,並初始化為 true
。
我們用 if
來判斷,在 showTask
為 true
的時候顯示 WellnessTaskItem
。運用我們前幾天學到的 remember
API 來確定 recomposition 後依然可以保留 showTask
。
@Composable
fun AngryCounter() {
Column(modifier = Modifier.padding(16.dp)) {
var count by remember { mutableStateOf(0) }
if (count > 0) {
var showTask by remember { mutableStateOf(true) }
if (showTask) {
WellnessTaskItem(
onClose = { },
taskName = "Take it easy, take a deep breath"
)
}
Text("You've got angry $count times today.")
}
Button(onClick = { count++ }, enabled = count < 10) {
Text("I feel Anger!")
}
}
}
我們要來使用 WellnessTaskItem
的 onClose
lambda 函式,當有人按下 X 按鈕時,不要顯示任務,並將 showTask
變數更改為 false
。
...
WellnessTaskItem(
onClose = { showTask = false },
taskName = "Take it easy, take a deep breath"
)
...
接下來請新增一個 Button
,寫上文字「Clear angry count」(清除生氣次數),然後把它放在「I feel Anger!」(我感到怒怒) Button
旁邊。我們可以使用 Row
來對齊這兩個按鈕。也可以在 Row
加入 padding。當有人按下「Clear angry count」(清除生氣次數) 的按鈕後,變數 count
就會重設為 0
。
我們的 AngryCounter
composable function 應該會像下面這樣:
import androidx.compose.foundation.layout.Row
@Composable
fun AngryCounter(modifier: Modifier = Modifier) {
Column(modifier = modifier.padding(16.dp)) {
var count by remember { mutableStateOf(0) }
if (count > 0) {
var showTask by remember { mutableStateOf(true) }
if (showTask) {
WellnessTaskItem(
onClose = { showTask = false },
taskName = "Take it easy, take a deep breath"
)
}
Text("You've got angry $count times today.")
}
Row(Modifier.padding(top = 8.dp)) {
Button(onClick = { count++ }, enabled = count < 10) {
Text("I feel Anger!")
}
Button(onClick = { count = 0 }, Modifier.padding(start = 8.dp)) {
Text("Clear angry count")
}
}
}
}
此系列文章是以我的業餘專案:Kimoji 為範例。
Kimoji 是一款心情日記 App,讓你用可愛的 emoji 來撰寫你的心情日記。現在就來試試這款設計精美的微日記吧!
立馬下載
Reference: https://developer.android.com/codelabs/jetpack-compose-state