一、概念
Styles API 提供了一种声明式且简化的方法,可以显著减少使用 Modifier 时的样板代码。
二、使用
2.1 自带交互的组件
当组件处于对应状态时,用指定的 Style 覆盖当前设置。这些状态可以嵌套使用,如悬停再按下。这些扩展函数(条件函数)底层都是从 StyleState 中读取的,受支持的组件底层已经做了更新状态的逻辑。
| StyleScope |
fun StyleScope.pressed(value: Style) 按下时。 |
|
fun StyleScope.hovered(value: Style) 悬停时。 | |
|
fun StyleScope.focused(value: Style) 聚焦时。 | |
|
fun StyleScope.selected(value: Style) 选择时。 | |
|
fun StyleScope.disabled(value: Style) 禁用时。 | |
|
fun StyleScope.triStateToggleOn(value: Style) 切换时。 | |
|
fun StyleScope.checked(value: Style) 为开时。 |
BaseButton(
onClick = { },
style = {
// 单独使用
focused { background(AppColor.Blue) }
// 嵌套使用:悬停并按下
hovered {
border(3.dp, Color.Black)
pressed { background(AppColor.Green) }
}
}
) { Text("点击") }
2.2 自定义组件
通过交互源 InteractionSource 来更新 StyleState。
| MutableStyleState | 构造 |
constructor(override val interactionSource: InteractionSource?) : StyleState() 根据交互源创建样式状态。 |
| 是否按下 |
var isPressed: Boolean | |
| 是否悬停 | var isHovered: Boolean | |
| 是否聚焦 | var isHovered: Boolean | |
| 是否启用 | var isEnabled: Boolean | |
| 是否选择 | var isSelected: Boolean | |
| 开关状态 |
var triStateToggle: ToggleableState 值分别为:开 On、关 Off、无法确定 Indeterminate。 | |
| 是否为开 |
var isChecked: Boolean 是否为 ToggleableState.On。 | |
| rememberUpdatedStyleState() |
inline fun rememberUpdatedStyleState( 创建、记忆并更新一个 StyleState。底层就是对 remember() + 构造函数 方式创建的包装,相比之下更适用于有函数参数更新样式状态时,如 enable 属性。 | |
使用 remember() 创建:
- 通过构造将 InteractionSource 传递给 MutableInteractionSource,将返回的 StyleState 传递给 Modifier.styleable()。
- 将 InteractionSource 传递给 Modifier.focusable()、Modifier.clickable() 等。
@Composable
fun Demo(
onClick: () -> Unit,
modifier: Modifier = Modifier,
style: Style = Style,
) {
val interactionSource = remember { MutableInteractionSource() }
val styleState = remember(interactionSource) { MutableStyleState(interactionSource) }
Box(
modifier = modifier
.styleable(styleState, style)
.clickable(interactionSource = interactionSource, onClick = onClick)
) { }
}
使用 rememberUpdatedStyleState() 创建:
- 通过 rememberUpdatedStyleState() 将 InteractionSource 连接到 StyleState,将返回的 StyleState 传递给 Modifier.styleable()。
- 将 InteractionSource 传递给 Modifier.focusable()、Modifier.clickable() 等。
@Composable
fun Demo(
onClick: () -> Unit,
modifier: Modifier = Modifier,
style: Style = Style,
enable: Boolean = true, // 有参数更新样式状态
) {
val interactionSource = remember { MutableInteractionSource() }
val styleState = rememberUpdatedStyleState(interactionSource) { mutableStyleState ->
// 通过参数更新状态
mutableStyleState.isEnabled = enable
}
Box(
modifier = modifier
.styleable(styleState, style)
.clickable(interactionSource = interactionSource, onClick = onClick)
) {...}
}
2.2 交互源联动
将 InteractionSource 添加为组件参数,如果外部未提供则在内部初始化。
@Composable
fun Demo(
interactionSource: MutableInteractionSource? = null,
) {
val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
}
三、动画
将属性变更用 animate{} 块包裹,这与 aninmate***AsState() 类似。
| animate() |
fun animate(value: Style) 动画默认为 spring 效果。 |
|
fun animate(spec: AnimationSpec<Float>, value: Style) 指定动画规格。 | |
|
fun animate(toSpec: AnimationSpec<Float>, fromSpec: AnimationSpec<Float>, value: Style) 分别指定进出场的动画规格。 |
Modifier.styleable = {
animate {
pressed { background(Color.Red) }
}
animate(spring(dampingRatio = Spring.DampingRatioMediumBouncy)) {
scale(1.2f)
}
}
四、自定义 StyleState
- 创建自定义键 StyleStateKey:提供默认值。
- 为 StyleState 添加扩展属性:自定义状态,获取和更新状态。
- 为 StyleScope 添加扩展函数:自定义条件函数,用来设置样式。
- 连接状态:自定义状态连接到扩展属性。
4.1 创建自定义键
enum class PlayerState {
Stopped, Playing, Paused
}
val playerStateKey = StyleStateKey(PlayerState.Stopped)
4.2 为 StyleState 添加扩展属性
var MutableStyleState.playerState
get() = this[playerStateKey]
set(value) { this[playerStateKey] = value }
4.3 为 StyleScope 添加扩展函数
| state() |
fun <T> state( 用于创建条件函数。 |
fun StyleScope.playerPlaying(value: Style) {
state(playerStateKey, value) { key, state -> state[key] == PlayerState.Playing }
}
fun StyleScope.playerPaused(value: Style) {
state(playerStateKey, value) { key, state -> state[key] == PlayerState.Paused }
}
4.4 连接状态
@Composable
fun Player(
modifier: Modifier = Modifier,
style: Style = Style,
// 将自定义状态作为参数传入
playerState: PlayerState = PlayerState.Stopped
) {
val styleState = remember { MutableStyleState(null) }
// 将自定义状态连接到样式状态
// 不要通过 key 来设置(styleState[playerStateKey] = playerState)
// key 属于 API 提供方使用,不应该是调用方使用
styleState.playerState = playerState
Box(
modifier = modifier.styleable(styleState, style)
) {...}
}
4.5 使用
@Composable
fun Demo() {
Player(
style = Style {
playerPaused {...}
playerPlaying {...}
}
)
}
&spm=1001.2101.3001.5002&articleId=161000703&d=1&t=3&u=9eeef309efa54ba7baceb11408f86e6d)
379

被折叠的 条评论
为什么被折叠?



