我使用包含多个 LazyRow 的 LazyColumn。
当焦点移动到另一行时,例如从A行移动到B行,我需要恢复A行最后聚焦的位置;当焦点回到A行时,我需要将焦点移动到恢复的位置。我怎样才能做到?
默认情况下,例如焦点位于 B 行第三个位置,当我单击向上按钮将焦点移回 A 行时,焦点也会移动到 A 行第三个位置。
在我的项目中,lazyRow 包含多个 AppCard,例如:
@Composable
fun AppCard(
app: App,
modifier: Modifier = Modifier,
onClick: (App) -> Unit = {}
) {
Card(
onClick = { onClick(app) },
modifier = modifier
.widthIn(max = 120.dp)
.aspectRatio(16f / 9f)
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
AsyncImage(
model = app.appIcon,
contentDescription = app.appName
)
}
}
}
我尝试在每个AppCard的修改器中初始化一个FocusRequester,但我发现很难知道焦点是否已经离开该行。对于每一行,我需要存储最后的焦点位置。
class CatalogViewModel : ViewModel() {
private val _categoriesMap = MutableStateFlow<Map<String, List<App>>>(emptyMap())
val categoriesMap: StateFlow<Map<String, List<App>>> = _categoriesMap
...
}
@Composable
fun CatalogBrowser(viewModel: CatalogViewModel) {
val categoriesMap by viewModel.categoriesMap.collectAsState(emptyMap())
LazyColumn(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = PaddingValues(horizontal = 48.dp, vertical = 32.dp)
) {
itemsIndexed(categoriesMap.entries.toList()) { categoryIndex, entry ->
val (category, appList) = entry
Column {
Text(text = category, modifier = Modifier.padding(start = 12.dp))
Spacer(modifier = Modifier.height(6.dp))
LazyRow(
modifier = Modifier.height(67.5.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp),
contentPadding = PaddingValues(horizontal = 10.dp),
) {
itemsIndexed(appList) { appIndex, app ->
val cardRequester = remember {
FocusRequester()
}
AppCard(
modifier = Modifier
.focusRequester(cardRequester)
.padding(vertical = 6.dp),
app = app,
onClick = { onCardSelected(app) }
)
}
}
}
}
}
}
现在我找到了解决方法。只需简单地将 focusRestorer 添加到修饰符即可修复它,如下所示:
Box(modifier = Modifier.focusRestorer()) {...}
我们还可以将 focusRequester 添加到 focusRestorer,以防使用我们自己的焦点逻辑。