Skip to content

Commit

Permalink
feat(Android): Add focused states on page transitions (software-mansi…
Browse files Browse the repository at this point in the history
…on#1894)

## Description

Currently, on Android TV devices when user is switching between views
the last focused child is lost. This seems like an incorrect behavior -
In software-mansion#1706 people are reporting that on Android TV the last focused
element should be stored.

This PR introduces the change to remember last focused element on
previous screen.
For now I've added a statement that the last element should be stored
only for Android TV, but we should discuss if we also should store those
elements for classic Android - I've noticed that it's possible to focus
an element on a normal screen, but I've achieved it only by switching
between elements with arrows on keyboard (so is it possible to focus an
element just by touching a screen? Maybe TalkBack is also focusing the
elements?).

<details><summary>
Focusing elements on Android
</summary>


https://github.com/software-mansion/react-native-screens/assets/23281839/4f62ae66-f411-4c45-b678-1e47c3fa4ff2

</details>

Fixes software-mansion#1706. 

## Changes

- Added `isTelevision` method that checks if user is currently using
Android TV.
- Added `lastFocusedChild` variable with an implementation for finding
last focused elements.

## Screenshots / GIFs

Here you can add screenshots / GIFs documenting your change.

You can add before / after section if you're changing some behavior.

### Before


https://github.com/software-mansion/react-native-screens/assets/23281839/0e3e0ad4-a202-43c3-b688-6c66f76a43f8

### After


https://github.com/software-mansion/react-native-screens/assets/23281839/998dfa5c-6def-47f2-b129-425a2257319a

## Test code and steps to reproduce

You can test those changes on `Example` application by switching between
examples with arrows on the keyboard.

## Checklist

- [ ] Ensured that CI passes
  • Loading branch information
tboba authored and ja1ns committed Oct 9, 2024
1 parent 3c2c559 commit 9fbc6c3
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.facebook.react.uimanager.PixelUtil
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.AppBarLayout.ScrollingViewBehavior
import com.swmansion.rnscreens.utils.DeviceUtils

class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
private var mAppBarLayout: AppBarLayout? = null
private var mToolbar: Toolbar? = null
private var mShadowHidden = false
private var mIsTranslucent = false

private var mLastFocusedChild: View? = null

var searchView: CustomSearchView? = null
var onSearchViewCreate: ((searchView: CustomSearchView) -> Unit)? = null

Expand Down Expand Up @@ -89,6 +92,11 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
}
}

override fun onStart() {
mLastFocusedChild?.requestFocus()
super.onStart()
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand Down Expand Up @@ -123,6 +131,13 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
return view
}

override fun onStop() {
if (DeviceUtils.isPlatformAndroidTV(context))
mLastFocusedChild = findLastFocusedChild()

super.onStop()
}

override fun onPrepareOptionsMenu(menu: Menu) {
updateToolbarMenu(menu)
return super.onPrepareOptionsMenu(menu)
Expand Down Expand Up @@ -163,6 +178,16 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
}
}

private fun findLastFocusedChild(): View? {
var view: View? = screen
while (view != null) {
if (view.isFocused) return view
view = if (view is ViewGroup) view.focusedChild else null
}

return null
}

override fun canNavigateBack(): Boolean {
val container: ScreenContainer? = screen.container
check(container is ScreenStack) { "ScreenStackFragment added into a non-stack container" }
Expand Down
12 changes: 12 additions & 0 deletions android/src/main/java/com/swmansion/rnscreens/utils/DeviceUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.swmansion.rnscreens.utils

import android.content.Context
import android.content.pm.PackageManager

object DeviceUtils {

fun isPlatformAndroidTV(context: Context?): Boolean {
return context?.packageManager?.hasSystemFeature(PackageManager.FEATURE_LEANBACK) == true
}

}

0 comments on commit 9fbc6c3

Please sign in to comment.