so i have an android tv project and my structure is like this
TvLazyColumn(
state = listState,
pivotOffsets = PivotOffsets(0.15F),
modifier = Modifier
.focusRequester(setFocusContinueWatch)
.onKeyEvent {
if (it.nativeKeyEvent.action == KeyEvent.ACTION_DOWN) {
when (it.nativeKeyEvent.keyCode) {
KeyEvent.KEYCODE_DPAD_UP -> {
if (selectedRow > 0) {
selectedRow--
isUpFromList = false
} else {
isUpFromList = true
setFocusContinueWatch.freeFocus()
isFocusOnListing = false
}
}
KeyEvent.KEYCODE_DPAD_DOWN -> {
if (selectedRow < sizeOfRows!!) {
selectedRow++
isFocusOnListing = true
isUpFromList = false
}
}
}
}
false
}
now above this i have 2 types of view one when focusonlisting and one on !focusonlisting so in case of !focusonlisting i have a button watchnowbutton. so i have a logic for indexing for gtting the selectedrow now when im at top row i press up and else block logic triggers
LaunchedEffect(isFocusOnListing) {
if (isUpFromList) {
setFocusContinueWatch.freeFocus()
watchNowBtnFocus = true
setFocusOnWatchNow.captureFocus()
}
}
now what happens when i press up from fist row index 0 is the focus is on the button as the color of button changes onfocus but also the focus stays on the row as well as it shows the border and when moving left right i am moving left and right in the row. now i have to press up one more time to actually go to button.
so i have an android tv project and my structure is like this
TvLazyColumn(
state = listState,
pivotOffsets = PivotOffsets(0.15F),
modifier = Modifier
.focusRequester(setFocusContinueWatch)
.onKeyEvent {
if (it.nativeKeyEvent.action == KeyEvent.ACTION_DOWN) {
when (it.nativeKeyEvent.keyCode) {
KeyEvent.KEYCODE_DPAD_UP -> {
if (selectedRow > 0) {
selectedRow--
isUpFromList = false
} else {
isUpFromList = true
setFocusContinueWatch.freeFocus()
isFocusOnListing = false
}
}
KeyEvent.KEYCODE_DPAD_DOWN -> {
if (selectedRow < sizeOfRows!!) {
selectedRow++
isFocusOnListing = true
isUpFromList = false
}
}
}
}
false
}
now above this i have 2 types of view one when focusonlisting and one on !focusonlisting so in case of !focusonlisting i have a button watchnowbutton. so i have a logic for indexing for gtting the selectedrow now when im at top row i press up and else block logic triggers
LaunchedEffect(isFocusOnListing) {
if (isUpFromList) {
setFocusContinueWatch.freeFocus()
watchNowBtnFocus = true
setFocusOnWatchNow.captureFocus()
}
}
now what happens when i press up from fist row index 0 is the focus is on the button as the color of button changes onfocus but also the focus stays on the row as well as it shows the border and when moving left right i am moving left and right in the row. now i have to press up one more time to actually go to button.
Share Improve this question edited Jan 19 at 18:33 tyg 14.9k4 gold badges34 silver badges47 bronze badges asked Jan 19 at 18:06 Priyanshu RajPriyanshu Raj 334 bronze badges 1- Based on the description, what you are trying to achieve is not super clear to me. Could you please attach screenshots of expected and actual behaviour? – vighnesh153 Commented Jan 20 at 4:45
2 Answers
Reset to default 0when you press up from the first row, you're getting a split focus state where both the button and the row appear to have focus, requiring an extra up press to fully move to the button.
Changes i made in your code:
1.Added true return values when handling UP/DOWN keys to consume events.
2.clear the row selection when moving up from the first row
3.Add a small delay in launcheffect.
This is your updated code with my comments:
TvLazyColumn(
state = listState,
pivotOffsets = PivotOffsets(0.15F),
modifier = Modifier
.focusRequester(setFocusContinueWatch)
.onKeyEvent {
if (it.nativeKeyEvent.action == KeyEvent.ACTION_DOWN) {
when (it.nativeKeyEvent.keyCode) {
KeyEvent.KEYCODE_DPAD_UP -> {
if (selectedRow > 0) {
selectedRow--
isUpFromList = false
} else {
isUpFromList = true
setFocusContinueWatch.freeFocus()
// Clear the row selection when moving up*
selectedRow = -1
// Or another invalid value*
isFocusOnListing = false
}
true
// Consume the event*
}
KeyEvent.KEYCODE_DPAD_DOWN -> {
if (selectedRow < sizeOfRows!!) {
selectedRow++
isFocusOnListing = true
isUpFromList = false
}
true
// Consume the event*
}
else -> false
}
} else false
}
)
Change this in Launcheffect:
LaunchedEffect(isFocusOnListing) {
if (isUpFromList) {
// Ensure complete focus transfer
setFocusContinueWatch.freeFocus()
delay(50) // Small delay to ensure focus release
watchNowBtnFocus = true
setFocusOnWatchNow.captureFocus()
}
}
Finally in Button you can add this for focus change:
Button(
modifier = Modifier
.focusRequester(setFocusOnWatchNow)
.onFocusChanged { state ->
watchNowBtnFocus = state.isFocused
if (state.isFocused) {
isFocusOnListing = false
}
}
)
so i got the solution
KeyEvent.KEYCODE_DPAD_UP -> {
if (selectedRow > 0) {
selectedRow--
isUpFromList = false
} else {
scope.launch{
isFocusOnListing = false
isUpFromList = true
delay(50)
setFocusContinueWatch.freeFocus()
setFocusOnWatchNow.requestFocus()
}
}
i just did the whole operation in a coroutine scope and added a 50milli delay