奇怪的Android RecyclerView(GridLayoutManager)焦点行为

奇怪的Android RecyclerView(GridLayoutManager)焦点行为,android,android-tv,android-recyclerview,Android,Android Tv,Android Recyclerview,我有一个带有GridLayoutManager的RecyclerView,每行2列。因为开发是为了安卓电视,所以我需要专注于导航 如果我使用向下键导航到任何可见的项目,这是可以的。例如,项目1->项目3->项目5->项目7(仅部分可见)。但当我再次按下向下键时,焦点将移到第10项而不是第9项 我的网格视图适配器是: public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder> {

我有一个带有GridLayoutManager的RecyclerView,每行2列。因为开发是为了安卓电视,所以我需要专注于导航

如果我使用向下键导航到任何可见的项目,这是可以的。例如,项目1->项目3->项目5->项目7(仅部分可见)。但当我再次按下向下键时,焦点将移到第10项而不是第9项

我的网格视图适配器是:

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);
        }
    }
}
公共类GridAdapter扩展了RecyclerView.Adapter{ 私有ArrayList数据集; 公共GridAdapter(ArrayList myDataset){ mDataset=myDataset; } @凌驾 公共视图持有者onCreateViewHolder(视图组视图组,int i){ 视图v=LayoutInflater.from(viewGroup.getContext()).flate(R.layout.grid_项,viewGroup,false); 视窗支架vh=新视窗支架(v); 返回vh; } @凌驾 公共无效onBindViewHolder(ViewHolder,int位置){ holder.txtitle.setText(mDataset.get(position)); } @凌驾 public int getItemCount(){ 返回mDataset.size(); } 公共静态类ViewHolder扩展了RecyclerView.ViewHolder{ 公共文本视图txtTitle; 公共视图持有者(视图v){ 超级(五); txtTitle=(TextView)v.findViewById(R.id.title); } } }
你知道如何解决这个问题吗?谢谢。

我想出了一个简单的答案。 除非新行充气,否则它将不允许滚动(因此它将等待新行充气),但通常需要不到50~100毫秒的时间。 因此,我们同意这种行为是可以接受的

只需获取onFocusSearchFailed以返回null。这里有一个例子

/**
 * 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;
    }
}
查看并解决您的问题

我向AOSP问题跟踪器报告了此错误:

正如我从源代码中看到的,这个问题是因为GridLayoutManager使用 LinearLayoutManager对onFocusSearchFailed()的实现 当焦点接近RecyclerView的内部边界时调用。 LinearLayoutManager的实现只提供第一个/最后一个(取决于 关于滚动方向)元素。因此,焦点跳到第一个/最后一个 新行的元素


你最终解决了这个问题吗?在过去的一两个月里,这一直在扰乱我的生活。不,我还没有找到任何解决办法。但它在我的应用程序中不是很关键,所以我只是把它放在那里。希望有人有一天能解决这个问题。导航文档说“Android框架会根据可聚焦元素在布局中的相对位置自动应用定向导航方案。”你能在适配器中设置nextFocusDown、nextFocusUp等吗?