关于如何给一个view设置圆角,有哪些方法呢?
1.给该view设置一个圆角的背景,这是最常见的用法。如以下代码:
round_bg.xml
- 1
- 2
- 3
- 4
- 5
- 6
- 7
.support.v7.widget.RecyclerView
android:id="@+id/rv_list_1"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_margin="20dp"
android:background="@drawable/round_bg" />
- 1
- 2
- 3
- 4
- 5
- 6
这种方式,正常情况下是没有问题的,可是如果想实现无缝的圆角显示,例如,它里面的一个列表,紧贴着边缘,即padding为0,会发现,圆角的那部分区域,还是有子view在显示的,并没有完全的实现真正的圆角,因为只是外层的背景圆角了而已。
那有什么办法让子view也圆角显示呢?下面说下第二种方法。
2.通过代码设置圆角,如下:
/**
* 设置视图裁剪的圆角半径
* @param radius
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void setClipViewCornerRadius(View view, final int radius){if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
//不支持5.0版本以下的系统
return;
}if(view == null) return;
if(radius <= 0){
return;
}/*view.setOutlineProvider(new ViewOutlineProvider() {@Override
public void getOutline(View view, Outline outline) {
outline.setRoundRect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom(), radius);
}
});
*/
view.setOutlineProvider(new ViewOutlineProvider() {@Override
public void getOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, view.getWidth(),view.getHeight(), radius);
}
});
view.setClipToOutline(true);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
那有没更合适的方法呢,所幸,5.0版本之后,增加了新的组件,CardView,它可以设置圆角,阴影等。
.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_margin="20dp"
app:cardBackgroundColor="#33ff0000"
app:cardCornerRadius="30dp">.support.v7.widget.RecyclerView
android:id="@+id/rv_list_2"
android:layout_width="150dp"
android:layout_height="150dp" />
.support.v7.widget.CardView>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
那还有没有更好的方法,真正解决圆角view和里面的子view,并且兼容5.0以下版本呢?答案也是有的。我们知道View的绘图时有调用draw方法,绘图机制可参考http://blog.csdn.net/leehong2005/article/details/7307456
View#draw方法,提供了一个最基本的绘制机制,子类通常不需要重写这个方法。我们可以通过查看其源码,在View的draw里面,它通常需要做以下几件事情:
1,绘制自己的背景,如果有的话,因为背景始终都在最后面,所以要先画。2,如果需要的话,保存canvas的layer来准备绘制渐变效果,比如说有alpha动画等。3,绘制View的内容,其实就是调用onDraw方法,让子类可以绘制自己的内容。4,绘制自己的child,具体怎么绘制孩子,ViewGroup会去重写相应的方法。基类的View只是把调用这绘制child的方法,当然这个方法在View里面,应该是什么都不做。5,如果需要的话,画渐变效果并还原保存的canvas层。6,绘制其他的元素,比如scrollbar等。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
注意第4点,绘制子view的方法,这样的话,如果在绘制子view之前,要是给canvas设置圆角的path,是不是就可以呢。
/**
* 圆角的RelativeLayout
*
*/public class RoundRectLayout extends RelativeLayout {private Path mPath;
private int mRadius;
private int mWidth;
private int mHeight;
private int mLastRadius;
public static final int MODE_NONE = 0;
public static final int MODE_ALL = 1;
public static final int MODE_LEFT = 2;
public static final int MODE_TOP = 3;
public static final int MODE_RIGHT = 4;
public static final int MODE_BOTTOM = 5;
private int mRoundMode = MODE_ALL;
public RoundRectLayout(Context context) {
super(context);
init();
}public RoundRectLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}private void init(){setBackgroundDrawable(new ColorDrawable(0x33ff0000));
mPath = new Path();
mPath.setFillType(Path.FillType.EVEN_ODD);
setCornerRadius(ViewUtil.dp2px(getContext(), 30));
}/**
* 设置是否圆角裁边
* @param roundMode
*/
public void setRoundMode(int roundMode){
mRoundMode = roundMode;
}/**
* 设置圆角半径
* @param radius
*/
public void setCornerRadius(int radius){
mRadius = radius;
}private void checkPathChanged(){if(getWidth() == mWidth && getHeight() == mHeight && mLastRadius == mRadius){
return;
}mWidth = getWidth();
mHeight = getHeight();
mLastRadius = mRadius;
mPath.reset();
switch (mRoundMode){
case MODE_ALL:
mPath.addRoundRect(new RectF(0, 0, mWidth, mHeight), mRadius, mRadius, Path.Direction.CW);
break;
case MODE_LEFT:
mPath.addRoundRect(new RectF(0, 0, mWidth, mHeight),
new float[]{mRadius, mRadius, 0, 0, 0, 0, mRadius, mRadius},
Path.Direction.CW);
break;
case MODE_TOP:
mPath.addRoundRect(new RectF(0, 0, mWidth, mHeight),
new float[]{mRadius, mRadius, mRadius, mRadius, 0, 0, 0, 0},
Path.Direction.CW);
break;
case MODE_RIGHT:
mPath.addRoundRect(new RectF(0, 0, mWidth, mHeight),
new float[]{0, 0, mRadius, mRadius, mRadius, mRadius, 0, 0},
Path.Direction.CW);
break;
case MODE_BOTTOM:
mPath.addRoundRect(new RectF(0, 0, mWidth, mHeight),
new float[]{0, 0, 0, 0, mRadius, mRadius, mRadius, mRadius},
Path.Direction.CW);
break;
}}@Override
public void draw(Canvas canvas) {if(mRoundMode != MODE_NONE){
int saveCount = canvas.save();
checkPathChanged();
canvas.clipPath(mPath);
super.draw(canvas);
canvas.restoreToCount(saveCount);
}else {
super.draw(canvas);
}}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
然后在这个view包裹在自 view外,
.support.v7.widget.RecyclerView
android:id="@+id/rv_list_4"
android:layout_width="150dp"
android:layout_height="150dp" />
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
以上四种方法各有利弊,大家可以选择自己合适的方式来实现圆角。
原文链接:https://blog.csdn.net/hesong1120/article/details/52005895