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:


<<:  Day 10 - 来谈谈在P5最常用的色彩学

>>:  Swift 新手-建立 Laravel 开发环境

[Matplotlib] Flatten()

ax.flatten(): Transform n*m to 1*nm 1-D Array fig...

Day 05: Anaconda虚拟环境建置 Conda

在撰写Python专案时,时常会遇到需要不同Python版本以及不同版本的Package的问题。建立...

Day23 - 使用Django-allauth整合社群登入

今天的实作内容主要根据网路资源进行。 Django并没有提供官方的社群登入整合模组,在第三方套件上,...

Day30 赛後心得

在这30天的比赛中,不知不觉的到最後一天了,虽然中间发生了点小插曲导致没有成功,但我还是希望能照样将...

Day25-React 效能优化篇-下篇(介绍 React Profiler)

在这篇文章中,将会介绍 React 提供的 Profiler API。 介绍 React Profi...