Search code examples
androidandroid-fragmentsfocusonbackpressed

Retain focus on previous fragment's view


Suppose I have 5 views (1,2,3,4,5) in a fragment A and each view is focusable. Then, if the current focus in fragment A is at view 3 and clicking that view loads a new fragment, let's say fragment B.

Now, is there any way that when I press back button, the focus is retained on view 3 of fragment A automatically?

Note: I have added those fragments in the backstack. But my fragment contains recycler views. Clicking on an item of recycler view will load another fragment and on back press the Main Activity gets the default focus. I can implement focusing on recycler view's first item by implementing fragment's onBackPressListener() method. But I have no idea on how to retain focus on a fragment as it was before.


Solution

  • for those who still searching for the solution, I tested many ways but this one was the best for me (Kotlin): Image

    Fragment A

    1- block fragment a descendant focusability in onStop() in FRAGMENT A to avoid giving focus to a random button by the activity on BACK

    override fun onStop() {
        println("**onStop")
        (view as ViewGroup?)?.descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS
        super.onStop()
    }
    

    2- make a lambda to do some things on a resume

    private var doOnResume: (() -> Unit?)? = null
    

    3- setup the fragment transition

       // add a lambda here too
    private fun gotoFragment(onResume: () -> Unit) {
    
        //initialize doOnResume here
        doOnResume = onResume
    
        (requireActivity() as MainActivity).apply {
            supportFragmentManager.commit {
                replace(R.id.app_container, DetailsFragment())
                addToBackStack(null)
            }
    
    
        }
    
    }
    

    4- I am using leanback RowSupportFragment it automatically set focus t the last item when you request focus to its verticalGridView

    listFragment.setOnContentClickedListener {
            gotoFragment {
                listFragment.verticalGridView.requestFocus()
            }
        }
    

    note you are able to give focus to any view you want

       private fun onPlayButtonClicked() {
        binding.playBTN.setOnClickListener {button->
            gotoFragment {
                button.requestFocus()
            }
    
        }
    
    }
    

    5- call your lambda in the onResume

       override fun onResume() {
       //unblock descendantFocusability again
        (view as ViewGroup?)?.descendantFocusability = ViewGroup.FOCUS_AFTER_DESCENDANTS
    
        //avoid crashing app when gridview is not initialized yet or any other reason
        try {
    
            doOnResume?.invoke()
        } catch (_:Exception) {
        }
        super.onResume()
    }