There is such a screen (Android TV)
I need to implement the following:
Everything works as needed except for the 5th point.
Here is the code:
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")
}
}
}
}
}
Here is the translation:
As far as I can imagine, it's necessary to remember the index from which the user moved to the right panel (let's say button 3) and track when the user presses left. When the user presses left, request focus on the saved index (in our example, 3). But I have two questions:
Any ideas are welcome :)
You can make use of the existing focusRestorer modifier to achieve this.
@Composable
fun App() {
Row {
LeftPanel()
RightPanel()
}
}
@Composable
fun LeftPanel() {
val firstItemFr = remember { FocusRequester() }
LazyColumn(Modifier.focusRestorer { firstItemFr }) {
item { ListItem(Modifier.focusRequester(firstItemFr)) }
item { ListItem() }
item { ListItem() }
item { ListItem() }
}
}
@Composable
fun RightPanel() {
val firstItemFr = remember { FocusRequester() }
LazyColumn(Modifier.focusRestorer { firstItemFr }) {
item { ListItem(Modifier.focusRequester(firstItemFr)) }
item { ListItem() }
item { ListItem() }
item { ListItem() }
}
}
LazyColumn
can also be replaced with LazyVerticalGrid
with 2 columns as you have done in your question. :)
When we visit an unvisited LazyColumn, since nothing was previously focused, it will move focus to the first item. If visiting a visited column, focusRestorer will move focus to the last focused item from that LazyColumn.