iT邦幫忙

2021 iThome 鐵人賽

DAY 11
1
Mobile Development

認真學 Compose - 對 Jetpack Compose 的問題與探索系列 第 11

D11/ 要怎麼顯示動態資料的畫面 - State

今天大概會聊到的範圍

  • State
  • Gesture Modifier

在之前,都只是在介紹比較靜態的畫面。但今天如果想要和使用者互動時,該如何處理呢?

Clickable

從最基礎的按鈕開始,按鈕有一個 parameter 是 onClick,這個 onClick lambda 就可以處理最基礎的互動。

Button(onClick = {}) {
    Text("button")
}

在原先的 Android view system,可以對每一個 View 做 click 。在 Compose 中一樣可以做到

Text("button", modifier = Modifier.clickable {  })

在任何的 Composable 上,都可以加上 clickable 這個 modifier,一樣可以做到點擊的互動。另外,還有 combinedClickable 這個 modifier ,可以設定長按、雙擊之類較少用的點擊事件。

Text(
    "button",
    modifier = Modifier.combinedClickable(
        onClick = { },
        onLongClick = { },
        onDoubleClick = { }
    )
)

State

在與使用者互動之後,可能就會有不同的資料需要顯示給 user 。在 Compose function 裡,我們可以用一般的 if-else / when 等判斷式來決定要顯示什麼資料。

var isClicked = false
    
Column {
    if (isClicked) {
        // 1.
        Text("Click me", modifier = Modifier.clickable { isClicked = true })
    } else {
        // 2.
        Text("Clicked")
    }
}

雖然我們在 1 這個 Text 上有設定一個 click 事件,將 isClicked 改成 false。但實際執行起來,會發現點擊了沒有效果。原因是因為 isClicked 這個變數改變後,不會觸發 recomposition。Recomposition 就是 Composable 重新執行 compose 的行為,recomposition 會因為 state 改變而觸發。有幾個不同的方法可建立 state

// 使用 remember 來建立
val isClickedState = remember { mutableStateOf(false) }

// 使用 delegate 
var isClicked by remember { mutableStateOf(false) }

在使用 delegate ( by ) 來建立 state 時,會需要 import androidx.compose.runtime.setValue 和 getVale

要使用時,如果用 delegate 的方式建立的 State,可以直接是為對應的型別賦值。如果用 remember 存放 state 的話,會需要透過 value 的 setter

Text("Click me",
    modifier = Modifier.clickable {
        isClicked = true
        // or
        isClickedState.value = true
    }
)

Stateful composable

當一個 composable 中,有自己控制自己的 State 時,就是一個 Stateful composable。Stateful 的 composable 可以自己處理自己的狀態,但同時,外部的元件就沒辦法控制他(或者說,需要一些 callback 來與外部互動)

相反的 Stateless 的 composable 是不自己處理 State 的 component。這不代表他沒有狀態,而可能是他的狀態是由外部控管的。

@Composable
fun StatelessComponent(isClicked: Boolean, whenClick: () -> Unit ) {
    Column {
        if (isClicked) {
            Text("Click me", modifier = Modifier.clickable { whenClick() })
        } else {
            Text("Clicked")
        }
    }    
}

將 State 交給外部的作法,稱為 state hoisting。透過 state hoisting ,我們可以一層一層將狀態提升到最外層,最後由統一個 ViewModel ( 或 Presenter 這類的角色 ) 進行控制。


今天先簡單題及了互動與狀態 (State),後續還會有更複雜的互動方式(例如 Drag & Drop),State 也會是動畫、互動等行為的基礎。


Reference:


上一篇
D10/ 我要怎麼把文字變美美的 - Text & AnnotatedString
下一篇
D12/ 我要怎麼用動畫改變中的資料? - Animations
系列文
認真學 Compose - 對 Jetpack Compose 的問題與探索30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言