Android 圆角装饰

Android 圆角装饰,android,android-recyclerview,android-canvas,android-view,android-custom-view,Android,Android Recyclerview,Android Canvas,Android View,Android Custom View,我有一个带有GridLayoutManager的RecyclerView,其中包含具有各种视图类型的项目(以及SpanSize)。我需要为所有R.layout.item_image类型设置圆角,如下图所示 因此,我创建了一个ItemDecoration,它计算将在其上绘制这些项目的Rect。然后将画布剪辑到此矩形(使用路径进行圆角): 公共类RoundCornersDecoration扩展了RecyclerView.ItemDecoration{ 私有最终浮动半径; 私有最终RectF def

我有一个带有GridLayoutManager的
RecyclerView
,其中包含具有各种
视图类型的项目(以及
SpanSize
)。我需要为所有
R.layout.item_image
类型设置圆角,如下图所示

因此,我创建了一个
ItemDecoration
,它计算将在其上绘制这些项目的
Rect
。然后将
画布
剪辑到此
矩形
(使用
路径
进行圆角):

公共类RoundCornersDecoration扩展了RecyclerView.ItemDecoration{
私有最终浮动半径;
私有最终RectF defaultRectToClip;
公共圆角装饰(浮动半径){
这个半径=半径;
defaultRectToClip=新的RectF(Float.MAX_值,Float.MAX_值,0,0);
}
@凌驾
公共void onDraw(画布画布、RecyclerView父级、RecyclerView.State){
最终RectF rectToClip=getRectToClip(父级);
//没有ViewType=`R.layout.item\u图像的项目`
if(rectToClip.equals(defaultRectToClip)){
返回;
}
最终路径=新路径();
addRoundRect(rectToClip,radius,radius,path.Direction.CW);
canvas.clipPath(路径);
}
私有RectF getRectToClip(RecyclerView父级){
最终RectF RECTOCLIP=新RectF(默认RECTOCLIP);
final Rect childRect=new Rect();
对于(int i=0;i
除图像下方未绘制任何其他项目外,一切正常。
我想那是因为我在画任何东西之前先剪辑画布。那么,我应该如何剪裁画布以节省圆角并绘制所有其他项目呢?

我终于找到了一个解决方案,它非常简单。我所需要做的就是提供
画布的另一部分

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

将其包含到路径中,然后剪辑:

    final Path path = new Path();
    path.addRoundRect(rectToClip, radius, radius, Path.Direction.CW);
    path.addRect(otherItemsRect, Path.Direction.CW);
    canvas.clipPath(path);
就这样。现在我们有了所有带有圆角的图片


另外,为了简单起见,我这里没有提供优化的代码

onCreateViewHolder
中,您可以创建根
视图
ViewHolder
-使用自定义
框架布局
作为“根视图”并重写其
dispatchDraw
方法-在那里,您可以剪裁画布,所有子视图都将剪裁为well@pskink如果我答对了,那么我需要检查那里的视图顺序(例如,剪裁左上角或剪裁右下角)是,在
onBindViewHolder
内部,您有
int位置
,因此您可以检查其顶部、中间或底部视图,并更改路径acordingly@pskink这样就不需要剪辑,而是在根视图
中设置一个具有适当
形状的背景。无论如何,我都不想将该逻辑公开到
ViewHolder
中,因为我在许多地方重复使用它。因此,我正在寻找一种方法,通过
ItemDecoration
来解决这个问题。但是谢谢你的建议。如果我没有其他选择,我将使用它。你不必触摸你的
视图持有者
s-你所需要的只是传递一个根
视图
,该视图剪辑了他们的子视图。请你详细说明一下这一点,并展示你是如何构造上述代码的。^另外,“创建一个新的rect”中是否有错误part?@VinayGaba你可以在这个要点中找到最终版本:“创建一个新的rect”部分没有错误。这只是一个较短的版本:
rectfotheritemsrect=newrectf();otherItemsRect.top=rectToClip.bottom;otherItemsRect.left=rectToClip.left;otherItemsRect.right=rectToClip.right;otherItemsRect.bottom=maxBottom我的错,我后来能理解你的逻辑:)谢谢!
    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;
    final Path path = new Path();
    path.addRoundRect(rectToClip, radius, radius, Path.Direction.CW);
    path.addRect(otherItemsRect, Path.Direction.CW);
    canvas.clipPath(path);