I used a RecyclerView with HORIZONTAL direction in my TV development which controlled by a D-pad to navigate the list from the left to right. the last item of the RecyclerView always lost focus when navigating to the right-most of the list.
So how can i keep the last item's focus when navigating to the end of the list?
notifyDataSetChanged. Notify any registered observers that the data set has changed. There are two different classes of data change events, item changes and structural changes. Item changes are when a single item has its data updated but no positional changes have occurred.
setHasFixedSize(true) means the RecyclerView has children (items) that has fixed width and height. This allows the RecyclerView to optimize better by figuring out the exact height and width of the entire list based on the your adapter.
If you're using a subclass of BaseGridView
, like HorizontalGridView
or VerticalGridView
, set an onKeyInterceptListener
that swallows the movement key at the end of the list. For example, with a HorizontalGridView
:
grid.setOnKeyInterceptListener { event ->
val focused = grid.focusedChild
event?.keyCode == KEYCODE_DPAD_RIGHT && grid.layoutManager.getPosition(focused) == grid.adapter.itemCount-1
}
If you're using RecyclerView
directly, then use onInterceptFocusSearch
with a custom LinearLayoutManager
. For example, with a LinearLayoutManager.VERTICAL
list:
list.layoutManager = object: LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) {
override fun onInterceptFocusSearch(focused: View?, direction: Int): View? {
if (direction == View.FOCUS_DOWN) {
val pos = getPosition(focused)
if (pos == itemCount-1)
return focused
}
if (direction == View.FOCUS_UP) {
val pos = getPosition(focused)
if (pos == 0)
return focused
}
return super.onInterceptFocusSearch(focused, direction)
}
}
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With