这是我之前question的后续内容。
在我的应用中,我正在尝试使用水平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
或我做错了什么?
答案 0 :(得分:4)
RecyclerView
有关于ItemDecoration
的自己的规则。他认为这些是项目本身的一部分。您可以想一想,decoration
(即使只是padding
)是my_item.xml
本身的一部分。
LinearSnapHelper
使用LayoutManager.getDecoratedMeasuredWidth()
等方法来确定视图的中心。这就是问题发生的地方。它会看到你的第一个项目比你想象的要大得多,所以第一个视图的中心位于(padding + view.getWidth()) / 2
。它比第二个视图的中心远得多,这是正常的view.getX() + view.getWidth() / 2
。