我有一个RecyclerView
与GridLayoutManager
,其中包含各种ViewTypes
(和SpanSize
s)的项目。我需要为所有R.layout.item_image
类型的角落,如下图所示
所以我创建了一个ItemDecoration
来计算将要绘制这些项目的Rect
。然后将Canvas
剪辑到这个Rect
(使用Path
到圆角):
public class RoundCornersDecoration extends RecyclerView.ItemDecoration {
private final float radius;
private final RectF defaultRectToClip;
public RoundCornersDecoration(float radius) {
this.radius = radius;
defaultRectToClip = new RectF(Float.MAX_VALUE, Float.MAX_VALUE, 0, 0);
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
final RectF rectToClip = getRectToClip(parent);
// has no items with ViewType == `R.layout.item_image`
if (rectToClip.equals(defaultRectToClip)) {
return;
}
final Path path = new Path();
path.addRoundRect(rectToClip, radius, radius, Path.Direction.CW);
canvas.clipPath(path);
}
private RectF getRectToClip(RecyclerView parent) {
final RectF rectToClip = new RectF(defaultRectToClip);
final Rect childRect = new Rect();
for (int i = 0; i < parent.getChildCount(); i++) {
if (!isImage(parent, i)) {
continue;
}
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, childRect);
rectToClip.left = Math.min(rectToClip.left, childRect.left);
rectToClip.top = Math.min(rectToClip.top, childRect.top);
rectToClip.right = Math.max(rectToClip.right, childRect.right);
rectToClip.bottom = Math.max(rectToClip.bottom, childRect.bottom);
}
return rectToClip;
}
private boolean isImage(RecyclerView parent, int viewPosition) {
final RecyclerView.Adapter adapter = parent.getAdapter();
final int viewType = adapter.getItemViewType(viewPosition);
return viewType == R.layout.item_image;
}
}
一切都很好,除了图像下面没有其他项目。我想这是因为我在实际绘制任何项目之前剪切画布。那么我该如何剪裁画布以保存圆角并覆盖所有其他物品?
我终于找到了解决方案而且非常简单。我需要做的就是提供canvas
的另一部分:
如您所见,顶部,左侧和右侧点与第一个矩形相同,因此我们只需要找到底部:
int maxBottom = 0;
final Rect childRect = new Rect();
for (int i = 0; i < parent.getChildCount(); i++) {
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, childRect);
maxBottom = Math.max(maxBottom, childRect.bottom);
}
创建一个新的矩形:
final RectF otherItemsRect = new RectF(rectToClip);
otherItemsRect.top = otherItemsRect.bottom;
otherItemsRect.bottom = maxBottom;
将其包含在Path
中然后剪辑:
final Path path = new Path();
path.addRoundRect(rectToClip, radius, radius, Path.Direction.CW);
path.addRect(otherItemsRect, Path.Direction.CW);
canvas.clipPath(path);
而已。现在我们所有的项目都有圆角图像
附:我没有按照简单的顺序提供优化的代码