圆角ItemDecoration

时间:2017-12-27 10:08:30

标签: android android-recyclerview android-canvas android-view android-custom-view

我有RecyclerView GridLayoutManager,其中包含各种ViewTypes(和SpanSize s)的项目。我需要为所有R.layout.item_image类型设置圆角,如下图所示

Round corners example

所以我创建了一个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;
    }
}

除了图片下方没有其他项目外,一切正常。 我想这是因为我在实际绘制任何项目之前剪切了画布。那么我应该如何剪裁画布以保存圆角并覆盖所有其他项目?

1 个答案:

答案 0 :(得分:0)

我终于找到了解决方案而且非常简单。我需要做的就是提供canvas其他部分

pic

正如您所见 top 点与第一个矩阵相同,因此我们只需找到< EM>底

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

就是这样。现在我们有所有带图像圆角的项目

附:我没有按照简单的顺序提供优化的代码