10

I have a RecyclerView with GridLayoutManager, with 2 columns per row. Because the develop is for Android TV so that I need focus to navigate.

enter image description here

It's ok if I'm using down key to navigate to any visible items. For example, Item 1 -> Item 3 -> Item 5 -> Item 7 (Only partially visible.). But when I press down key again, the focus will move to Item 10 instead of 9.

enter image description here

My grid view adapter is:

public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder> {    
    private ArrayList<String> mDataset;

    public GridAdapter(ArrayList<String> myDataset) {
        mDataset = myDataset;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.grid_item, viewGroup, false);
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.txtTitle.setText(mDataset.get(position));    
    }

    @Override
    public int getItemCount() {
        return mDataset.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView txtTitle;
        public ViewHolder(View v) {
            super(v);
            txtTitle = (TextView) v.findViewById(R.id.title);
        }
    }
}

Any idea how to solve this issue? Thanks.

ataulm
  • 15,195
  • 7
  • 50
  • 92
Bagusflyer
  • 12,675
  • 21
  • 96
  • 179
  • 2
    Did you end up solving this? This has been messing up my life for the past month or two. – Dreamingwhale Apr 29 '15 at 18:53
  • No, I didn't find any solution yet. But it's not very critical in my application so I just kept it there. Hope somebody can solve the issue someday. – Bagusflyer May 20 '15 at 09:08
  • The Navigation docs say this "The Android framework automatically applies a directional navigation scheme based on the relative position of focusable elements in your layouts." Can you set the nextFocusDown, nextFocusUp, etc. in your adapter somehow? – Elrond Jun 10 '15 at 21:34

2 Answers2

2

View this related post and Vganin's answer for resolve your problem.

I reported this bug to AOSP issue tracker: issue 190526

As I can see from source the issue is because GridLayoutManager uses LinearLayoutManager's implementation of onFocusSearchFailed() which is called when focus approaches the inner border of RecyclerView. LinearLayoutManager's implementation just offers first/last (depends on scrolling direction) element. Hence focus jumps to first/last element of new row.

My workaround for this issue.

Community
  • 1
  • 1
Crisic
  • 1,181
  • 1
  • 9
  • 27
0

I figured out a hack answer to this. It won't let you scroll unless the new row is inflated (So it'll wait on the new row being inflated.) but it normally takes less than 50~100 ms. So we agreed that the behaviour is acceptable.

Just get onFocusSearchFailed to return null. Here's an example.

/**
 * Created by sylversphere on 15-04-22.
 */
public class DelayedNaviGridLayoutManager extends GridLayoutManager{

    private final Context context;

    public SomeGridLayoutManager(Context context, int spanCount) {
        super(context, spanCount);
        this.context = context;
    }

    public SomeGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
        super(context, spanCount, orientation, reverseLayout);
        this.context = context;
    }

    @Override
    public View onFocusSearchFailed(View focused, int focusDirection, RecyclerView.Recycler recycler, RecyclerView.State state) {
        return null;
    }
}
Nick is tired
  • 6,860
  • 20
  • 39
  • 51
Dreamingwhale
  • 433
  • 6
  • 22