LinearSnapHelper无法将RecyclerView的边缘项目对齐

9
这是我之前提出的问题的跟进。
在我的应用程序中,我正在尝试拥有一个水平RecyclerView,它会自动对齐到中心项。为此,我附加了一个LinearSnapHelper。我还创建了一个项目装饰,将一些左/右填充添加到第一个/最后一个元素中:
public class OffsetItemDecoration extends RecyclerView.ItemDecoration {

    private Context ctx;

    public OffsetItemDecoration(Context ctx){
        this.ctx = ctx;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int nCols = ActivityUtils.getNumCols(ctx);
        int colWidth = (int)(getScreenWidth()/(float)(nCols));

        if(parent.getChildAdapterPosition(view) == 0){
            int offset = Math.round(getScreenWidth() / 2f - colWidth / 2f);
            setupOutRect(outRect, offset, true);
        }

        else if (parent.getChildAdapterPosition(view) == state.getItemCount()-1){
            int offset = Math.round(getScreenWidth() / 2f - colWidth / 2f);
            setupOutRect(outRect, offset, false);
        }
    }

    private void setupOutRect(Rect rect, int offset, boolean start){
        if(start) rect.left = offset;
        else rect.right = offset;
    }

    private  int getScreenWidth(){
        WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        return size.x;
    }
}

问题在于当RecyclerView第一次填充时,第一项会居中显示并被选中,但是当我尝试水平滚动并返回到第一项时,最左边的可选项是第二项(位置1)。对于最后一项也是同样的情况,可以对齐到最右边的项是倒数第二项(state.getItemCount() - 2)。
我需要实现一个新的SnapHelper还是我做错了什么?

那是因为listView的长度问题。第一个和最后一个项目无法到达。我曾经遇到过类似的问题,只需添加默认不可见的项目来弥补无法到达的区域即可。但是,为此,您需要针对不同屏幕大小进行一些计算。但这只是一种hacky-wacky的解决方案,也许(希望如此)有更好的解决方案。 - Opiatefuchs
@Opiatefuchs 理论上,我“ItemDecoration”添加的人工偏移应该会防止我创建这样的虚拟项。 - Vektor88
是的……理论上……我在偏移量方面没有取得任何成功。但这不适合我的需求。我的目标是拥有一个水平的RecyclerView,让条目从左到右(反之亦然)滑到屏幕末尾。偏移量会裁剪边缘,而且条目无法滚动到屏幕末尾。因为这个问题,我决定添加一些不可见的视图直到找到另一个解决方案。 - Opiatefuchs
1个回答

10

RecyclerView 有关于 ItemDecoration 的自己的规则。它认为它们是项目本身的一部分。你可以想象,你的 decoration (即使只是一个 padding) 是你的 my_item.xml 本身的一部分。

LinearSnapHelper 使用像 LayoutManager.getDecoratedMeasuredWidth() 这样的方法来确定视图的中心。这就是问题出现的地方。它看到你的第一个项目比你想象的要大得多,因此第一个视图的中心实际上在 (padding + view.getWidth()) / 2 中。它比第二个视图的中心要远得多,而第二个视图的中心通常为 view.getX() + view.getWidth() / 2


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