我有一个带有GridLayoutManager
的RecyclerView
,其中包含具有各种ViewTypes
(以及SpanSize
)的项目。 我需要为所有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;
}
}
除了图像下方没有绘制其他项之外,一切都正常。我猜这是因为在实际绘制任何项之前,我剪辑了画布。那么我应该如何剪辑画布以保存圆角并显示所有其他项?
onCreateViewHolder
方法中,您需要创建根View
和ViewHolder
。使用自定义的FrameLayout
作为您的 "根视图",并覆盖其dispatchDraw
方法。在那里,您可以剪切画布,并且所有子视图也将被剪切。 - pskinkonBindViewHolder
中你有int position
,所以你可以检查它是否为顶部、中间或底部视图,并相应地更改路径。 - pskink<corners .. />
形状的背景将更简单。无论如何,我不想将该逻辑暴露到ViewHolder
中,因为我在许多地方重用它。因此,我正在寻找通过ItemDecoration
解决它的方法。 但是感谢您的建议。如果没有其他选择,我会使用它。 - Nikolay KulachenkoViewHolder
,你只需要传递一个根View
来裁剪它们的子视图。 - pskink