我有一个这样的屏幕(Andorid TV)
我需要这样做:
- 当屏幕打开时,焦点位于左侧面板中的第一个视图上(左侧面板:0)
- 用户可以(在遥控器上)上下切换左侧面板中的元素
- 如果用户按向右,焦点将移至第一个视图中的右侧面板(右侧面板:0)
- 用户可以根据需要在右侧面板中的元素之间移动焦点
- 如果用户位于左侧堆栈的右侧面板中,按向左键,则焦点应移动到左侧面板到从其转到右侧面板的元素。也就是说,如果用户位于左侧面板中的第三个元素上并向右按下,那么当他从右侧面板返回到左侧时,焦点应移回到他之前所在的第三个元素。
总的来说,除了第 5 点之外,一切都正常
这是代码
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Test_delete_itTheme {
Surface(
modifier = Modifier.fillMaxSize(),
shape = RectangleShape
) {
Greeting()
}
}
}
}
}
@Composable
fun Greeting() {
val leftPanelFocusRequester: FocusRequester = remember { FocusRequester() }
val rightPanelFocusRequester: FocusRequester = remember { FocusRequester() }
Row(modifier = Modifier
.fillMaxSize()
) {
LeftPanel(
focusRequester = leftPanelFocusRequester,
onRightDirectionClicked = {
rightPanelFocusRequester.requestFocus()
}
)
RightPanel(focusRequester = rightPanelFocusRequester)
}
}
@Composable
fun RowScope.LeftPanel(
focusRequester: FocusRequester,
onRightDirectionClicked: () -> Unit
) {
LaunchedEffect(Unit) {
this.coroutineContext.job.invokeOnCompletion {
focusRequester.requestFocus()
}
}
Column(
modifier = Modifier
.background(Color.Blue.copy(alpha = 0.1f))
.fillMaxHeight()
.weight(1f)
.onKeyEvent {
if (it.key == Key.DirectionRight) {
onRightDirectionClicked()
true
} else {
false
}
},
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
repeat(5) {
Button(
modifier = Modifier
.let { modifier ->
if (it == 0) {
modifier.focusRequester(focusRequester)
} else {
modifier
}
},
onClick = { }
) {
Text(text = "Left Panel: $it")
}
}
}
}
@Composable
fun RowScope.RightPanel(focusRequester: FocusRequester) {
Column(
modifier = Modifier
.background(Color.Green.copy(alpha = 0.1f))
.fillMaxHeight()
.weight(1f),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
val buttons by rememberSaveable { mutableStateOf(List(10) { "Button ${it + 1}" }) }
LazyVerticalGrid(
columns = GridCells.Fixed(2),
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
itemsIndexed(
items = buttons,
key = { idx, _ -> idx }
) { idx, _ ->
Button(
modifier = Modifier
.padding(8.dp)
.let {
if (idx == 0) {
it.focusRequester(focusRequester)
} else {
it
}
}
,
onClick = { }
) {
Text(text = "Right Panel: $idx")
}
}
}
}
}
据我想象,您需要记住用户转到右侧面板的索引(假设按钮3)并跟踪用户向左的单击,当用户单击向左时,然后请求将焦点放在保存的索引(在我们的示例 3 中)。但这2个问题
- 如何区分右侧面板元素之间的右键单击(例如,右侧面板 3 -> 右侧面板 2 单击)和所需的单击(例如,右侧面板:6 -> 左侧面板 3)?
- 在我看来,这个解决方案看起来太麻烦了,不知何故,这一切应该更简单。
欢迎任何想法:)
UPD
我还有一个相关的问题,如果有人感兴趣欢迎 - https://ru.stackoverflow.com/a/1586671/195957
最后,我使用了
focusRestorer
该功能,这样它本身就会记住最后的焦点位置。但我必须说,这帮助我找到了我在问题中描述的问题的解决方案,但出现了我在这个问题中描述的另一个问题 - >当您返回屏幕时如何将焦点分配到同一位置?(如果有人有任何想法请告诉我)
这是我得到的代码,作为该线程中提出的问题的解决方案