Assigned
Status Update
Comments
lp...@google.com <lp...@google.com> #2
This actually has nothing to do with NavHostFragment, but is the behavior of NavController's setGraph().
When you call navController.setGraph(R.navigation.navigation_graph), it stores that ID and will restore that ID automatically.
If you were to instead use:
NavInflater navInflater = new NavInflater(this, navController.getNavigatorProvider());
navController.setGraph(navInflater.inflate(R.navigation.navigation_graph));
Then NavController would not restore the graph itself and the call to restoreState() you point out would only restore the back stack state, etc. but would wait for you to call setGraph again.
You're right that the inconsistency between the two setGraph methods is concerning. We'll take a look.
When you call navController.setGraph(R.navigation.navigation_graph), it stores that ID and will restore that ID automatically.
If you were to instead use:
NavInflater navInflater = new NavInflater(this, navController.getNavigatorProvider());
navController.setGraph(navInflater.inflate(R.navigation.navigation_graph));
Then NavController would not restore the graph itself and the call to restoreState() you point out would only restore the back stack state, etc. but would wait for you to call setGraph again.
You're right that the inconsistency between the two setGraph methods is concerning. We'll take a look.
ra...@google.com <ra...@google.com> #3
Turns out, we already had a tracking bug for this issue, will follow up on that other one.
ra...@google.com <ra...@google.com> #4
Thank you for promptly replying to my report. You are right that the issue you've just mentioned is similar to mine. I shall continue observing the progress over there.
ap...@google.com <ap...@google.com> #5
Project: platform/frameworks/support
Branch: androidx-main
Author: Ralston Da Silva <
Link:
Fix bug in focus restoration
Expand for full commit details
Fix bug in focus restoration
aosp/3318176 and aosp/3251331 in combination introduced
a regression in focus restoration. requestFocus() now
automatically cancels any previous focus transactions.
We were cancelling the current focus transaction which
ended up clearing the restored focus.
Bug: 387516723
Test: Added a new test
Change-Id: I12bfed62a322f02ed633b17ce8c581b503b31538
Files:
- M
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/FocusRestorerTest.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRestorer.kt
Hash: 3a912e9b314ac61e5b0153f1abc969462d9b2f3b
Date: Thu Feb 06 16:02:51 2025
ka...@paramount.com <ka...@paramount.com> #6
Thanks for fixing the regression!
Removal of `focusTarget` from the Item above didn't help. Focus is still not restored properly. Crash is still reproducible.
I was able to "kind of fix it", by changing the code above to store focused child on each key down event:
```
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
val colFocusRequester = remember { FocusRequester() }
LazyColumn(
modifier = Modifier
.focusRequester(overallFr)
.focusRequester(colFocusRequester)
.focusRestorer { focusRequester }
.onPreviewKeyEvent {
when (it.nativeKeyEvent.keyCode) {
KEYCODE_DPAD_LEFT,
KEYCODE_SYSTEM_NAVIGATION_LEFT,
KEYCODE_DPAD_UP,
KEYCODE_SYSTEM_NAVIGATION_UP,
KEYCODE_DPAD_RIGHT,
KEYCODE_SYSTEM_NAVIGATION_RIGHT,
KEYCODE_DPAD_DOWN,
KEYCODE_SYSTEM_NAVIGATION_DOWN,
KEYCODE_DPAD_CENTER,
KEYCODE_ENTER,
-> {
if (it.nativeKeyEvent.action == KeyEvent.ACTION_DOWN) {
colFocusRequester.saveFocusedChild()
}
}
else -> {
// do nothing
}
}
false
}
```
but it seems like a huge hack ;)
Complete code of "fixed" problem:
```
import android.os.Bundle
import android.view.KeyEvent
import android.view.KeyEvent.KEYCODE_DPAD_CENTER
import android.view.KeyEvent.KEYCODE_DPAD_DOWN
import android.view.KeyEvent.KEYCODE_DPAD_LEFT
import android.view.KeyEvent.KEYCODE_DPAD_RIGHT
import android.view.KeyEvent.KEYCODE_DPAD_UP
import android.view.KeyEvent.KEYCODE_ENTER
import android.view.KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN
import android.view.KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT
import android.view.KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT
import android.view.KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP
import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.BringIntoViewSpec
import androidx.compose.foundation.gestures.LocalBringIntoViewSpec
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.focusRestorer
import androidx.compose.ui.focus.focusTarget
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.unit.dp
import androidx.fragment.app.FragmentActivity
class MainActivity : FragmentActivity() {
@OptIn(ExperimentalComposeUiApi::class, ExperimentalFoundationApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.main_activity)
findViewById<ComposeView>(R.id.left)?.apply {
setContent {
LazyColumn(
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
items(5) {
Item(it.toString())
}
}
}
}
findViewById<ComposeView>(R.id.right)?.apply {
val overallFr = FocusRequester()
isFocusable = true
setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
try {
overallFr.requestFocus()
} catch (ex: IllegalStateException) {
println("PACZPAN crash $ex")
}
}
}
setContent {
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
val colFocusRequester = remember { FocusRequester() }
LazyColumn(
modifier = Modifier
.focusRequester(overallFr)
.focusRequester(colFocusRequester)
.focusRestorer { focusRequester }
.onPreviewKeyEvent {
when (it.nativeKeyEvent.keyCode) {
KEYCODE_DPAD_LEFT,
KEYCODE_SYSTEM_NAVIGATION_LEFT,
KEYCODE_DPAD_UP,
KEYCODE_SYSTEM_NAVIGATION_UP,
KEYCODE_DPAD_RIGHT,
KEYCODE_SYSTEM_NAVIGATION_RIGHT,
KEYCODE_DPAD_DOWN,
KEYCODE_SYSTEM_NAVIGATION_DOWN,
KEYCODE_DPAD_CENTER,
KEYCODE_ENTER,
-> {
if (it.nativeKeyEvent.action == KeyEvent.ACTION_DOWN) {
colFocusRequester.saveFocusedChild()
}
}
else -> {
// do nothing
}
}
false
},
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
items(4) { colIdx ->
AnimatedVisibility(true, modifier =Modifier
.conditional(
condition = colIdx == 0,
ifTrue = { focusRequester(focusRequester) },
)
.onFocusChanged {
if (it.isFocused) {
focusManager.moveFocus(FocusDirection.Enter)
}
},) {
Column(
) {
val inRowFr = remember { FocusRequester() }
val gridFr = remember { FocusRequester() }
Text("Column $colIdx", color = Color.Black)
CompositionLocalProvider(
LocalBringIntoViewSpec provides object : BringIntoViewSpec {
},
) {
LazyVerticalGrid(
modifier = Modifier
.heightIn(max = 300.dp)
.focusRequester(gridFr)
.focusRestorer { inRowFr }
.onPreviewKeyEvent {
when (it.nativeKeyEvent.keyCode) {
KEYCODE_DPAD_LEFT,
KEYCODE_SYSTEM_NAVIGATION_LEFT,
KEYCODE_DPAD_UP,
KEYCODE_SYSTEM_NAVIGATION_UP,
KEYCODE_DPAD_RIGHT,
KEYCODE_SYSTEM_NAVIGATION_RIGHT,
KEYCODE_DPAD_DOWN,
KEYCODE_SYSTEM_NAVIGATION_DOWN,
KEYCODE_DPAD_CENTER,
KEYCODE_ENTER,
-> {
if (it.nativeKeyEvent.action == KeyEvent.ACTION_DOWN) {
gridFr.saveFocusedChild()
}
}
else -> {
// do nothing
}
}
false
},
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalArrangement = Arrangement.spacedBy(10.dp),
columns = GridCells.Fixed(4),
) {
items(5) { rowIdx ->
Item(
index = "$rowIdx",
modifier = Modifier.conditional(
condition = rowIdx == 0,
ifTrue = { focusRequester(inRowFr) },
)
)
}
}
}
}
}
}
}
}
}
}
}
@Composable
fun Item(index: String, modifier: Modifier = Modifier) {
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
Box(
modifier = modifier
.clickable(
interactionSource = interactionSource,
indication = null,
onClick = {},
)
.background(if (isFocused) Color.Red else Color.Gray)
.focusTarget() // Doesn't matter if it is here or not
.size(100.dp),
contentAlignment = Alignment.Center,
) {
Text(text = index, color = Color.White)
}
}
```
Removal of `focusTarget` from the Item above didn't help. Focus is still not restored properly. Crash is still reproducible.
I was able to "kind of fix it", by changing the code above to store focused child on each key down event:
```
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
val colFocusRequester = remember { FocusRequester() }
LazyColumn(
modifier = Modifier
.focusRequester(overallFr)
.focusRequester(colFocusRequester)
.focusRestorer { focusRequester }
.onPreviewKeyEvent {
when (it.nativeKeyEvent.keyCode) {
KEYCODE_DPAD_LEFT,
KEYCODE_SYSTEM_NAVIGATION_LEFT,
KEYCODE_DPAD_UP,
KEYCODE_SYSTEM_NAVIGATION_UP,
KEYCODE_DPAD_RIGHT,
KEYCODE_SYSTEM_NAVIGATION_RIGHT,
KEYCODE_DPAD_DOWN,
KEYCODE_SYSTEM_NAVIGATION_DOWN,
KEYCODE_DPAD_CENTER,
KEYCODE_ENTER,
-> {
if (it.nativeKeyEvent.action == KeyEvent.ACTION_DOWN) {
colFocusRequester.saveFocusedChild()
}
}
else -> {
// do nothing
}
}
false
}
```
but it seems like a huge hack ;)
Complete code of "fixed" problem:
```
import android.os.Bundle
import android.view.KeyEvent
import android.view.KeyEvent.KEYCODE_DPAD_CENTER
import android.view.KeyEvent.KEYCODE_DPAD_DOWN
import android.view.KeyEvent.KEYCODE_DPAD_LEFT
import android.view.KeyEvent.KEYCODE_DPAD_RIGHT
import android.view.KeyEvent.KEYCODE_DPAD_UP
import android.view.KeyEvent.KEYCODE_ENTER
import android.view.KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN
import android.view.KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT
import android.view.KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT
import android.view.KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP
import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.BringIntoViewSpec
import androidx.compose.foundation.gestures.LocalBringIntoViewSpec
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.focusRestorer
import androidx.compose.ui.focus.focusTarget
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.unit.dp
import androidx.fragment.app.FragmentActivity
class MainActivity : FragmentActivity() {
@OptIn(ExperimentalComposeUiApi::class, ExperimentalFoundationApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.main_activity)
findViewById<ComposeView>(R.id.left)?.apply {
setContent {
LazyColumn(
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
items(5) {
Item(it.toString())
}
}
}
}
findViewById<ComposeView>(R.id.right)?.apply {
val overallFr = FocusRequester()
isFocusable = true
setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
try {
overallFr.requestFocus()
} catch (ex: IllegalStateException) {
println("PACZPAN crash $ex")
}
}
}
setContent {
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
val colFocusRequester = remember { FocusRequester() }
LazyColumn(
modifier = Modifier
.focusRequester(overallFr)
.focusRequester(colFocusRequester)
.focusRestorer { focusRequester }
.onPreviewKeyEvent {
when (it.nativeKeyEvent.keyCode) {
KEYCODE_DPAD_LEFT,
KEYCODE_SYSTEM_NAVIGATION_LEFT,
KEYCODE_DPAD_UP,
KEYCODE_SYSTEM_NAVIGATION_UP,
KEYCODE_DPAD_RIGHT,
KEYCODE_SYSTEM_NAVIGATION_RIGHT,
KEYCODE_DPAD_DOWN,
KEYCODE_SYSTEM_NAVIGATION_DOWN,
KEYCODE_DPAD_CENTER,
KEYCODE_ENTER,
-> {
if (it.nativeKeyEvent.action == KeyEvent.ACTION_DOWN) {
colFocusRequester.saveFocusedChild()
}
}
else -> {
// do nothing
}
}
false
},
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
items(4) { colIdx ->
AnimatedVisibility(true, modifier =Modifier
.conditional(
condition = colIdx == 0,
ifTrue = { focusRequester(focusRequester) },
)
.onFocusChanged {
if (it.isFocused) {
focusManager.moveFocus(FocusDirection.Enter)
}
},) {
Column(
) {
val inRowFr = remember { FocusRequester() }
val gridFr = remember { FocusRequester() }
Text("Column $colIdx", color = Color.Black)
CompositionLocalProvider(
LocalBringIntoViewSpec provides object : BringIntoViewSpec {
},
) {
LazyVerticalGrid(
modifier = Modifier
.heightIn(max = 300.dp)
.focusRequester(gridFr)
.focusRestorer { inRowFr }
.onPreviewKeyEvent {
when (it.nativeKeyEvent.keyCode) {
KEYCODE_DPAD_LEFT,
KEYCODE_SYSTEM_NAVIGATION_LEFT,
KEYCODE_DPAD_UP,
KEYCODE_SYSTEM_NAVIGATION_UP,
KEYCODE_DPAD_RIGHT,
KEYCODE_SYSTEM_NAVIGATION_RIGHT,
KEYCODE_DPAD_DOWN,
KEYCODE_SYSTEM_NAVIGATION_DOWN,
KEYCODE_DPAD_CENTER,
KEYCODE_ENTER,
-> {
if (it.nativeKeyEvent.action == KeyEvent.ACTION_DOWN) {
gridFr.saveFocusedChild()
}
}
else -> {
// do nothing
}
}
false
},
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalArrangement = Arrangement.spacedBy(10.dp),
columns = GridCells.Fixed(4),
) {
items(5) { rowIdx ->
Item(
index = "$rowIdx",
modifier = Modifier.conditional(
condition = rowIdx == 0,
ifTrue = { focusRequester(inRowFr) },
)
)
}
}
}
}
}
}
}
}
}
}
}
@Composable
fun Item(index: String, modifier: Modifier = Modifier) {
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
Box(
modifier = modifier
.clickable(
interactionSource = interactionSource,
indication = null,
onClick = {},
)
.background(if (isFocused) Color.Red else Color.Gray)
.focusTarget() // Doesn't matter if it is here or not
.size(100.dp),
contentAlignment = Alignment.Center,
) {
Text(text = index, color = Color.White)
}
}
```
Description
Jetpack Compose component used: focusRestorer on LazyColumn
Android Studio Build: Android Studio Ladybug | 2024.2.1 Patch 3
Kotlin version: 2.1.0
I wanted to report problems with focusRestorer that I've encountered.
First and the most important issue is that when we create a Row with 2 LazyColumns side by side and apply `focusRestorer` on one of them, the focus restoration doesn't work on 2024.12.01-alpha Compose BOM. On beta and release versions it's working just fine.
Second problem is the one that was my initial issue that I've tried to reproduce. `focusRestorer` is not working when we use in legacy view interoperability scenario. To reproduce this problem I've created an Activity with 2 ComposeViews next to each other. When focus moves from one to another `focusRestorer` doesn't save focused children. From my debugging it looks like `onExit` callback is not invoked when focus exits the ComposeView, hence the `focusRestorer` has no idea that it should `saveFocusedChild`.
Here are libs used:
agp = "8.7.3"
kotlin = "2.1.0"
coreKtx = "1.15.0"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
lifecycleRuntimeKtx = "2.8.7"
activityCompose = "1.9.3"
composeBom = "2024.12.01"
androidx-navigation = "2.8.5"
androidx-constrLayout = "2.2.0"
main_activity.xml
```
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="
xmlns:app="
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<androidx.compose.ui.platform.ComposeView
android:id="@+id/left"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:layout_constraintEnd_toStartOf="@id/right"
app:layout_constraintStart_toStartOf="parent" />
<androidx.compose.ui.platform.ComposeView
android:id="@+id/right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/left" />
</androidx.constraintlayout.widget.ConstraintLayout>
```
MainActivity.kt
```
class MainActivity : FragmentActivity() {
@OptIn(ExperimentalComposeUiApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.main_activity)
findViewById<ComposeView>(R.id.left)?.apply {
setContent {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
items(5) {
Item(it.toString())
}
}
}
}
findViewById<ComposeView>(R.id.right)?.apply {
setContent {
Row() {
if (true) {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
items(5) {
Item(it.toString())
}
}
Spacer(Modifier.size(10.dp))
}
val focusRequester = remember { FocusRequester() }
LazyColumn(
modifier = Modifier
.focusRestorer { focusRequester },
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
items(200) { colIdx ->
val focusManager = LocalFocusManager.current
Column(
Modifier
.ifElse(
condition = colIdx == 0,
ifTrueModifier = Modifier.focusRequester(focusRequester),
)
.onFocusChanged {
if (it.isFocused) {
focusManager.moveFocus(FocusDirection.Enter)
}
},
) {
Text("Column $colIdx", color = Color.Black)
LazyRow(
horizontalArrangement = Arrangement.spacedBy(10.dp),
) {
items(20) { rowIdx ->
Item(
index = "$rowIdx",
)
}
}
}
}
}
}
}
}
}
}
@Composable
fun Item(index: String, modifier: Modifier = Modifier) {
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
Box(
modifier = modifier
.focusable(interactionSource = interactionSource)
.background(if (isFocused) Color.Red else Color.Gray)
.focusTarget()
.size(100.dp),
contentAlignment = Alignment.Center,
) {
Text(text = index, color = Color.White)
}
}
```
In MainActivity.kt there's a hardcoded `if (true)` block. With this block `focusRestorer` works - it stores which row was selected before focus was moved away. But if we change that to `if (false)`, `focusRestorer` doesn't work anymore. In fact if we scroll down the right LazyColumn, so that the first row is not visible, we can get a crash, because it tries to focus the first row, which is not anymore in Composition.
```
23:51:55.631 12959-12959 AndroidRuntime FATAL EXCEPTION: main (Ask Gemini)
Process: com.magmagen.tvtestapp, PID: 12959
java.lang.IllegalStateException:
FocusRequester is not initialized. Here are some possible fixes:
1. Remember the FocusRequester: val focusRequester = remember { FocusRequester() }
2. Did you forget to add a Modifier.focusRequester() ?
3. Are you attempting to request focus during composition? Focus requests should be made in
response to some event. Eg Modifier.clickable { focusRequester.requestFocus() }
at androidx.compose.ui.focus.FocusRequester.findFocusTargetNode$ui_release(FocusRequester.kt:254)
at androidx.compose.ui.focus.FocusRequester.focus$ui_release(FocusRequester.kt:67)
at androidx.compose.ui.focus.FocusTransactionsKt.performCustomEnter-Mxy_nc0(FocusTransactions.kt:297)
at androidx.compose.ui.focus.FocusTransactionsKt.performCustomRequestFocus-Mxy_nc0(FocusTransactions.kt:275)
at androidx.compose.ui.focus.FocusTransactionsKt.performCustomRequestFocus-Mxy_nc0(FocusTransactions.kt:274)
at androidx.compose.ui.focus.FocusTransactionsKt.requestFocus-Mxy_nc0(FocusTransactions.kt:49)
at androidx.compose.ui.platform.AndroidComposeView$requestFocus$1.invoke(AndroidComposeView.android.kt:876)
at androidx.compose.ui.platform.AndroidComposeView$requestFocus$1.invoke(AndroidComposeView.android.kt:872)
at androidx.compose.ui.focus.FocusOwnerImpl$focusSearch$1.invoke(FocusOwnerImpl.kt:253)
at androidx.compose.ui.focus.FocusOwnerImpl$focusSearch$1.invoke(FocusOwnerImpl.kt:249)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.searchChildren-4C6V_qg(TwoDimensionalFocusSearch.kt:185)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.generateAndSearchChildren-4C6V_qg(TwoDimensionalFocusSearch.kt:155)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.searchChildren-4C6V_qg(TwoDimensionalFocusSearch.kt:188)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.generateAndSearchChildren-4C6V_qg(TwoDimensionalFocusSearch.kt:155)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.searchChildren-4C6V_qg(TwoDimensionalFocusSearch.kt:188)
at androidx.compose.ui.focus.TwoDimensionalFocusSearchKt.twoDimensionalFocusSearch-sMXa3k8(TwoDimensionalFocusSearch.kt:63)
at androidx.compose.ui.focus.FocusTraversalKt.focusSearch-0X8WOeE(FocusTraversal.kt:109)
at androidx.compose.ui.focus.FocusOwnerImpl.focusSearch-ULY8qGw(FocusOwnerImpl.kt:249)
at androidx.compose.ui.platform.AndroidComposeView.requestFocus(AndroidComposeView.android.kt:872)
at android.view.ViewRootImpl$ViewPostImeInputStage.performFocusNavigation(ViewRootImpl.java:6882)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:7001)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6811)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6229)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6286)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6252)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6417)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6260)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:6474)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6233)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6286)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6252)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6260)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6233)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6286)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6252)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6450)
at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:6661)
at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:4278)
23:51:55.632 12959-12959 AndroidRuntime at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:3715) (Ask Gemini)
at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:3706)
at android.view.inputmethod.InputMethodManager.-$$Nest$mfinishedInputEvent(Unknown Source:0)
at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:4255)
at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:154)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loopOnce(Looper.java:162)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
```
And as I wrote at the beginning - regardless of everything on 2024.12.01-alpha Compose BOM - `focusRestorer` doesn't work at all.