如何在专注于电视 LazyRow 的同时始终专注于第一项?

2023-12-06

我正在尝试实现一个 TVLazyRow,当我们关注该行上方其他可组合项的行时,它必须始终首先关注第一个项目。目前,按下时,焦点将转到行中位于上面可组合项正下方的项目。我怎样才能实现这种行为?

这是我的代码以获取更多上下文:

val tvListState = rememberTvLazyListState()
val coScope = rememberCoroutineScope()

TvLazyRow(
        horizontalArrangement = Arrangement.spacedBy(15.dp),
        state = tvListState,
        modifier = modifier
            .fillMaxHeight()
            .padding(end = 5.dp)
            .onFocusChanged {
                if (it.isFocused) {
                    coScope.launch {
                        tvListState.scrollToItem(0)
                    }
                }
            }, pivotOffsets = PivotOffsets(0f)
) { *items* }

最新日期:2023 年 11 月 1 日

焦点恢复 API 现已得到改进,并接受回退焦点请求程序,该请求程序将在访问未访问列表时使用。由于这一新的更改,我们现在不需要我之前创建的修改器工厂。

val firstChildFr = remember { FocusRequester() }

TvLazyRow(
  modifier = Modifier.focusRestorer { firstChildFr }
) {
  item { 
    Button(
      onClick = {}, 
      modifier = Modifier.focusRequester(firstChildFr)
    ) { 
      Text("My Button 1") 
    } 
  }
  item { Button(onClick = {}) { Text("My Button 2") } }
  item { Button(onClick = {}) { Text("My Button 3") } }
  // ...
}

2023 年 8 月 11 日编辑

您可以使用最近在 compose Foundation 的 alpha 版本中发布的 focusRestoration API。参考:saveFocusedChild() and 恢复FocusedChild()

您可以点击 focusProperties,当焦点进入容器时,您可以检查是否有先前保存的焦点子项。如果是,则将焦点转移到该孩子,否则,将焦点转移到第一个孩子。退出容器时,您可以保存之前获得焦点的子项。

您可以创建以下修改器工厂,它将为您抽象出此逻辑:

data class FocusRequesterModifiers(
    val parentModifier: Modifier,
    val childModifier: Modifier
)

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun createFocusRestorationModifiers(): FocusRequesterModifiers {
    val focusRequester = remember { FocusRequester() }
    val childFocusRequester = remember { FocusRequester() }

    val parentModifier = Modifier
        .focusRequester(focusRequester)
        .focusProperties {
            exit = {
                focusRequester.saveFocusedChild()
                FocusRequester.Default
            }
            enter = {
                if (!focusRequester.restoreFocusedChild())
                    childFocusRequester
                else
                    FocusRequester.Cancel
            }
        }

    val childModifier = Modifier.focusRequester(childFocusRequester)

    return FocusRequesterModifiers(parentModifier, childModifier)
}

上面的工厂就位后,您可以在惰性容器中使用它,如下所示:

val modifiers = createFocusRestorationModifiers()

TvLazyRow(
  modifier = Modifier.then(modifiers.parentModifier)
) {
  item { 
    Button(
      onClick = {}, 
      modifier = Modifier.then(modifiers.childModifier)
    ) { 
      Text("My Button 1") 
    } 
  }
  item { Button(onClick = {}) { Text("My Button 2") } }
  item { Button(onClick = {}) { Text("My Button 3") } }
  // ...
}

请注意,在上面的示例用法中,我们只需将父修饰符分配给TvLazyRow容器和第一项的子修饰符。如果您希望第二个或第三个项目第一次获得焦点,您也可以选择将其分配给第二个或第三个项目。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在专注于电视 LazyRow 的同时始终专注于第一项? 的相关文章

随机推荐