android/tv: fix focus highlighting on back buttons (#605)

updates tailscale/corp#26199

The back buttons would not highlight properly when
they are focussed on Android TV.  This pulls in what
was implemented for the Avatar.

Some small tweaks to the action animation so that it
has a nice radius instead of a square box.

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
pull/606/head
Jonathan Nobels 10 months ago committed by GitHub
parent 56d7be331e
commit 7f93377c2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -42,7 +42,7 @@ fun Avatar(
action: (() -> Unit)? = null,
isFocusable: Boolean = false
) {
var isFocused = remember { mutableStateOf(false) }
val isFocused = remember { mutableStateOf(false) }
val focusManager = LocalFocusManager.current
// Outer Box for the larger focusable and clickable area

@ -4,6 +4,7 @@
package com.tailscale.ipn.ui.view
import androidx.annotation.StringRes
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusable
import androidx.compose.foundation.interaction.MutableInteractionSource
@ -11,6 +12,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.CheckCircle
@ -24,10 +26,14 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.tailscale.ipn.ui.theme.topAppBar
@ -77,23 +83,32 @@ fun Header(
@Composable
fun BackArrow(action: () -> Unit, focusRequester: FocusRequester) {
val modifier =
val isFocused = remember { mutableStateOf(false) }
val boxModifier =
if (isAndroidTV()) {
Modifier.focusRequester(focusRequester)
.focusable() // Ensure the composable can receive focus
.clip(CircleShape) // Ensure both the focus and click area are circular
.background(
if (isFocused.value) MaterialTheme.colorScheme.surface else Color.Transparent,
)
.onFocusChanged { focusState -> isFocused.value = focusState.isFocused }
.focusable()
} else {
Modifier
}
Box(modifier = modifier.padding(start = 8.dp, end = 8.dp)) {
val iconModifier =
Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(bounded = false, radius = 24.dp),
onClick = action)
Box(modifier = boxModifier.padding(start = 8.dp, end = 8.dp)) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Go back to the previous screen",
modifier =
Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(bounded = true),
onClick = action))
modifier = iconModifier)
}
}

Loading…
Cancel
Save