Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Focus lost when fragment is on top of another fragment

Image for understanding of problem

Hello everyone. I have a Fragment A. From there I add Fragment B with .add() because I want to see Fragment A as a background. Everything is okay so far. Problem is, that I can focus out of Fragments B recyclerview item and navigate in Fragment A - which I would like to avoid. Is there a solution? If so, how? Is there a way to disable focusability on Fragment A?

I tried something like this (pseudo-code)

Activity "X":

onBackStackChange 
    if fragment B is on top {
        fragment A.getView.setFocusability = false;
    }

Any other ideas?

P.S. This is actually on Android TV using Leanback library. There might be a solution to go a route and disable focus on Fragment A using leanback built-ins, but I'm pretty sure there's other standart way of doing this.

About Card View - https://developer.android.com/training/tv/playback/card.html

like image 477
JohnCoolGuy1996 Avatar asked Nov 08 '22 15:11

JohnCoolGuy1996


1 Answers

I had exactly the same problem and I found this duplicate: Disable focus on fragment

The accepted solution worked for me.

Here is my version of the implementation so far (it can be improved):

abstract class BaseFragment<....> : Fragment() {

    private val screenFocusHelper = ScreenFocusHelper()

    fun enableFocus() {
        if (view != null) {
            // Enable focus
            screenFocusHelper.setEnableView(view as ViewGroup, true)

            // Clear focusable elements
            screenFocusHelper.focusableViews.clear()
        }

        childFragmentManager.fragments.forEach {
            if (it is BaseFragment<*, *>) {
                it.enableFocus()
            }
        }
    }

    fun disableFocus() {
        if (view != null) {
            // Store last focused element
            screenFocusHelper.previousFocus = view?.findFocus()

            // Clear current focus
            view!!.clearFocus()

            // Disable focus
            screenFocusHelper.setEnableView(view as ViewGroup, false)
        }

        childFragmentManager.fragments.forEach {
            if (it is BaseFragment<*, *>) {
                it.disableFocus()
            }
        }
    }

}

class ScreenFocusHelper {

    var previousFocus: View? = null

    val focusableViews: MutableList<View> = mutableListOf()

    fun setEnableView(viewGroup: ViewGroup, isEnabled: Boolean) {
        findFocusableViews(viewGroup)

        for (view in focusableViews) {
            view.isEnabled = isEnabled
            view.isFocusable = isEnabled
        }
    }

    private fun findFocusableViews(viewGroup: ViewGroup) {
        val childCount = viewGroup.childCount
        for (i in 0 until childCount) {
            val view = viewGroup.getChildAt(i)
            if (view.isFocusable) {
                if (!focusableViews.contains(view)) {
                    focusableViews += view
                }
            }
            if (view is ViewGroup) {
                findFocusableViews(view)
            }
        }
    }

}
like image 51
Eduard Avatar answered Nov 15 '22 10:11

Eduard