Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop dpad focus going outside current fragment in android

My current app requires control using a D-Pad remote.

Using Focus/Select, automatic calculation of nearest neighbour works as expected but i want to limit the Up, Down, Left, Right movements to only occur in the current fragment that contains the focused view, and cancel the change of focus before it moves to another fragment.

I am programatically changing focus to a new fragment upon selecting a view.

Is this possible to do? I can only assume an onFocusChange() event would allow me to check whether the new focus is outside the fragment and return but no luck here...

like image 343
Deminetix Avatar asked Oct 21 '22 02:10

Deminetix


1 Answers

In short, you can call setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS) on container that holds your fragment to block focusability for all fragment descendants. To bring focusability back you can call setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS)

Details:

Suppose you have FrameLayout containing two fragments, one on top another, and you want to limit focus navigation to top_fragment when it is in place and to back_fragment otherwise:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/back_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <FrameLayout
        android:id="@+id/top_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout> 

First call addOnBackStackChangedListener() on instance of FragmentManager to provide backstack listener, where you can write you focusability controlling code with method setDescendantFocusability. You can use getFragmentManager().findFragmentBy* to find out what fragments are used now, what's on top etc. and set descendant focusability flags appropriately. When you are replacing top_fragment container, add transaction to backstack with addToBackStack() method. That way you will be able to change focusability settings when backstack changes, not only when you're adding fragment, but when you're popping it with BACK as well.

like image 109
Vsevolod Ganin Avatar answered Oct 24 '22 05:10

Vsevolod Ganin