Column和Row可以理解为在View/Layout体系中的纵向和横向的ViewGroup
Column(
verticalArrangement:Arrangement // 控制纵向布局关系
horizontalAlignment:Alignment // 控制横向对齐关系
)
Row(
horizontalArrangement:Alignment // 控制横向布局关系
verticalAlignment:Arrangement // 控制纵向对齐关系
)
@Composable
fun TestColumnRow() {
Column(
modifier = Modifier.fillMaxHeight().background(Color.Yellow),
verticalArrangement = Arrangement.SpaceBetween,
horizontalAlignment = Alignment.Start
) {
Text(text = “java”)
Text(text = “android”)
Text(text = “python”)
}
Row(
modifier = Modifier.fillMaxWidth().background(Color.LightGray),
verticalAlignment = Alignment.Top,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(text = “java”)
Text(text = “android”)
Text(text = “python”)
}
}
四、进阶使用
状态管理
所有 Android 应用都有核心界面更新循环,如下所示:
Compose 专为单向数据流而打造。这是一种状态向下流动而事件向上流动的设计。
使用单向数据流的应用的界面更新循环如下所示:
事件:事件由界面的一部分生成并且向上传递。
更新状态:事件处理脚本可以更改状态。
显示状态:状态会向下传递,界面会观察新状态并显示该状态。
举两个例子展示:
//内部状态管理
@Composable
fun CounterInner() {
val count = remember { mutableStateOf(0) }
Button(onClick = { count.value += 1 })
{
Text(text = “Count: ${count.value}”)
}
}
解释一下上图的数据流情况
事件:当点击发生时候,会触发count.value
更新状态:mutableStateOf会进行处理,然后设置count的状态
显示状态:系统会调用count的观察器,并且界面会显示新状态
//支持其他可观察类型的状态管理
class CountViewModel : ViewModel() {
// LiveData holds state which is observed by the UI
// (state flows down from ViewModel)
private val _count = MutableLiveData(0)
val count: LiveData = _count
// onNameChanged is an event we’re defining that the UI can invoke
// (events flow up from UI)
fun onCountChanged(newCount: Int) {
_count.value = newCount
}
}
@Composable
fun Counter(countViewModel: CountViewModel = viewModel()) {
val observeAsState = countViewModel.count.observeAsState(0)
val count = observeAsState.value
Button(
colors = ButtonConstants.defaultButtonColors(backgroundColor = if (count > 5) Color.Green else Color.White),
onClick = { countViewModel.onCountChanged(count + 1) },
) {
Text(text = “I’ve been clicked $count times”)
}
}
解释一下上图的数据流情况
事件:当点击发生时候,会触发onCountChanged
更新状态:onCountChanged会进行处理,然后设置_count的状态
显示状态:系统会调用count的观察器,并且界面会显示新状态
状态提升
-
无状态可组合项是指本身无法改变任何状态的可组合项。无状态组件更容易测试、发生的错误往往更少,并且更有可能重复使用。
-
如果您的可组合项有状态,您可以通过使用状态提升使其变为无状态。
-
状态提升是一种编程模式,在这种模式下,通过将可组合项中的内部状态替换为参数和事件,将状态移至可组合项的调用方。
-
状态提升的过程可让您将单向数据流扩展到无状态可组合项。在这些可组合项的单向数据流示意图中,随着更多可组合项与状态交互,状态仍向下流动,而事件向上流动。
@Composable
fun Counter(countViewModel: CountViewModel = viewModel()) {
val observeAsState = countViewModel.count.observeAsState(0)
val count = observeAsState.value
ButtonCount(count = count, onCountChanged = { countViewModel.onCountChanged(it) })
}
@Composable
fun ButtonCount(
/* state */ count: Int,
/* event */ onCountChanged: (Int) -> Unit ) {
Button(
colors = ButtonConstants.defaultButtonColors(backgroundColor = if (count > 5) Color.Green else Color.White),
onClick = { onCountChanged(count + 1) },
) {
Text(text = “I’ve been clicked $count times”)
}
}
互操作
Android View中的Compose
如果想使用Compose的情况下,又不想迁移整个应用,可以在xml里面增加ComposeView,类似于占位符,然后在Actviity/fragment中寻找该控件并调用setContent方法即可,在该方法中即可使用compose相关属性
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.AndroidViewComposeActivity”>
<TextView
android:id=“@+id/hello_world”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:text=“Hello Android!”
app:layout_constraintTop_toTopOf=“parent” />
<a