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

10

我有一个使用GridLayoutManager的RecyclerView,每行有2个列。由于该开发是为了Android TV而进行的,因此我需要焦点进行导航。

enter image description here

如果我使用向下键导航到任何可见项,那么就可以正常工作。例如,Item 1-> Item 3-> Item 5-> Item 7(仅部分可见)。但是当我再次按下向下键时,焦点将移动到Item 10而不是9。

enter image description here

我的网格视图适配器如下:

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);
        }
    }
}

你有什么想法来解决这个问题吗?谢谢。


2
你最终解决了这个问题吗?这个问题在过去的一个月或两个月中一直困扰着我的生活。 - Dreamingwhale
不,我还没有找到任何解决方案。但在我的应用程序中这并不是非常关键的问题,所以我只是将其保留在那里。希望有一天有人能够解决这个问题。 - Bagusflyer
导航文档中提到:“Android框架会根据布局中可聚焦元素的相对位置自动应用方向导航方案。”你能否在适配器中以某种方式设置nextFocusDown、nextFocusUp等属性? - Elrond
2个回答

2

查看这个相关的帖子Vganin的答案来解决你的问题。

我向AOSP问题跟踪器报告了这个错误:问题190526

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

我的解决方法。


0

我找到了一个解决方法。

除非新行被充气(因此它将等待新行被充气),否则它不会让您滚动。但通常只需要不到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;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接