工作记录
Todo
Process
差不多写完了 timeline screen, 现在改叫 TopicLogScreen. 里面包含了 timeline + composer.
主要处理了下外层捕获事件的问题。
学到一个技巧:
Screen 当做多个 ViewModel 的协调器 如果需要在 ViewModel 之间做一些互操作,那么可以这么做:
- 在 ScreenRoute (smart 组件) 里直接注入 2 个 viewModel: Screen(viewModelA, viewModelB)
- 利用已有的两个 viewModel,写好交互操作的 action, 传入到需要的地方
- 关键点来了:将 2 个 viewModel 对应的 ScreenRoute, 通过 Lambda 函数传给 ScreenContent (dumb 组件),这种方式,也就保证了 ScreenContent 还是可以方便 preview 的!
@Composable
fun TopicLogScreen(
...
timelineViewModel: TimelineViewModel = hiltViewModel(),
composerViewModel: MessageComposerViewModel = hiltViewModel(),
) {
val focusManager = LocalFocusManager.current
val handleComposerDismiss = { // 互操作
focusManager.clearFocus()
composerViewModel.clearInputMode()
}
TopicLogContent(
...
// ViewModel 对应的组件,这里通过 lambda 传递
timelineSection = {
TimelineScreen(
// 传递互操作
onTapOutside = handleComposerDismiss,
onDragList = handleComposerDismiss,
timelineViewModel = timelineViewModel,
)
},
composerSection = {
MessageComposer(
onNavigateBack = onNavigateBack,
viewModel = composerViewModel,
)
},
handleComposerDismiss = handleComposerDismiss
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopicLogContent(
...
// 这个 lambda 同样可以接受参数, 所以也可以接受来自 Content 部分的内容
timelineSection: @Composable () -> Unit,
composerSection: @Composable () -> Unit,
// 传递互操作
handleComposerDismiss: () -> Unit,
) {
Column() {
Box(
modifier = modifier
.weight(1f)
.pointerInput(Unit) {
detectTapGestures {
handleComposerDismiss()
}
}) {
timelineSection()
}
composerSection()
}
}
还学到一个原则:子组件在父组件里的布局、动画定义,写到父组件里,子组件定义好自己内部的东西就好了。
生活记录
早上又下了一点雨。