Android Tv Recyclerview Set Next Focus of Its Item

Android TV RecyclerView focus interaction

Recycler view works fine with android TV.Possible solutions you can include are:

1.add focusable and focusableInTouchode to view.Add focusListner through the code and request focus each time when the view is clicked.

2.To keep Recycler View focused item in the centre you have to override layout manager just like this example.

RecyclerView smoothScroll to position in the center. android

or

use layoutManager.scrollToPositionWithOffset(position,offset) where position-focused view position and offset is the recycler view width/2.

How to keep the last item's focus of RecyclerView when navigating to the end of the list?

I dug into the source code of RecyclerView, i found the onInterceptFocusSearch method in the LayoutManager, inner class of RecyclerView.

/**
* This method gives a LayoutManager an opportunity to intercept the initial focus search
* before the default behavior of {@link FocusFinder} is used. If this method returns
* null FocusFinder will attempt to find a focusable child view. If it fails
* then {@link #onFocusSearchFailed(View, int, RecyclerView.Recycler, RecyclerView.State)}
* will be called to give the LayoutManager an opportunity to add new views for items
* that did not have attached views representing them. The LayoutManager should not add
* or remove views from this method.
*
* @param focused The currently focused view
* @param direction One of { @link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
* {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT},
* {@link View#FOCUS_BACKWARD}, {@link View#FOCUS_FORWARD}
* @return A descendant view to focus or null to fall back to default behavior.
* The default implementation returns null.
*/
public View onInterceptFocusSearch(View focused, int direction) {
return null ;
}

which gives a LayoutManager an opportunity to intercept the initial focus search before the default behavior of FocusFinder is used.

So i overrided the onInterceptFocusSearch likes below, and used the CustomGridLayoutManager for my RecylerView, which works like a charming.

public class CustomGridLayoutManager extends android.support.v7.widget.GridLayoutManager {

public CustomGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super (context, attrs, defStyleAttr, defStyleRes);
}

public CustomGridLayoutManager(Context context, int spanCount) {
super (context, spanCount);
}

public CustomGridLayoutManager(Context context, int spanCount, int orientation,
boolean reverseLayout) {
super (context, spanCount, orientation, reverseLayout);
}

@Override
public View onInterceptFocusSearch(View focused, int direction) {
int pos = getPosition(focused);
int count = getItemCount();
int orientation = getOrientation();


**********
do some logic
what i did was return the focused View when the focused view is the last item of RecyclerView.
**********

return super .onInterceptFocusSearch(focused, direction);
}
}

Prevent Recyclerview from losing focus

First of all i worked for 3 years on AndroidTv fighting against the focus management, it is actually pretty simple, the problem is...there is no documentation!

On Android-TV the right way to manage the Dpad navigation is actually to use the focusSearch method. What does this do?

DPad navigation actually means the focus changes between some Views. So who should decide where the focus should go when you press Dpad-Right? The ViewGroup (the parent) containing the Views does!

A little background: when a view does not know who should get the focus it asks the ViewGroup to take the decision. So in most cases when you push DpadRight while in focus on a View, focusSearch is called on its container with direction = FOCUS_RIGHT (FOCUS_END) and so on.

The solution for you is then pretty simple. You have 2 ways:
1. Put the Recyclerview inside a BrowseFrameLayout then you can do the following

BrowseFrameLayout browseFrameLayout = view.findViewById(R.id.recyclerview_container);
RecyclerView recyclerView = view.findViewById(R.id.categories_rv);
theBrowseFrameLayout.setOnFocusSearchListener(new BrowseFrameLayout.OnFocusSearchListener() {
@Override
public View onFocusSearch(View focused, int direction) {
if (recyclerView.hasFocus())
return focused; // keep focus on recyclerview! DO NOT return recyclerview, but focused, which is a child of the recyclerview
else
return null; // someone else will find the next focus
}
});

  1. You can create a custom view extending any container you are using for your recyclerview and do the same, here is a little more complex example that we use with an UI having a top menu and various fragments under it https://gist.github.com/RedLann/bfaffc06eb0f571234c6e46b697d633b

NOTE: Usually in xml we use on recyclerview android:descendantFocusability="afterDescendants"
NOTE: Just so you know when a View gets focused for the first time, there is a method of that view that is called, which is:

protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect)

NOTE: If you use this approach the focus management becomes really easy, each Parent view (ViewGroup/Container) will manage the focus for its direct children, when it doesn't know what to do it can delegate to its own parent viewgroup returning super.focusSearch

Android TV move focus between RecyclerViews

Digging through Google's Leanback library sources answered my payers.
If you face the same trouble, just wrap your RecyclerViews with this and don't forget to set

private boolean mPersistFocusVertical = false;

if you want the focus to be persisted when searching horizontally, like in my layout.

How to log in two different types of users to different activities automatically without having to log in again?



Related Topics



Leave a reply



Submit