圆角ItemDecoration

问题描述 投票:4回答:1

我有一个RecyclerViewGridLayoutManager,其中包含各种ViewTypes(和SpanSizes)的项目。我需要为所有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;
    }
}

一切都很好,除了图像下面没有其他项目。我想这是因为我在实际绘制任何项目之前剪切画布。那么我该如何剪裁画布以保存圆角并覆盖所有其他物品?

android android-recyclerview android-canvas android-view android-custom-view
1个回答
0
投票

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

pic

如您所见,顶部,左侧和右侧点与第一个矩形相同,因此我们只需要找到底部:

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

而已。现在我们所有的项目都有圆角图像

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

© www.soinside.com 2019 - 2024. All rights reserved.