前言:我们项目当中经常碰到要对某个图片控件做成圆角,或者动态改变它的圆角率,一般的做法如下
/**
* 获得圆角图片
* @param bitmap
* @param roundPx
* @return
* Bitmap.createBitmap 很容易出现oom,尽量不要使用
*/
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
paint.setAntiAlias(true);
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
但是此种方式一直在createBitmap容易出现性能问题,于是我就在想,有没有不会出现性能问题而且还可以通用的方式呢,基于此,下面的万能圆角类诞生了
万能圆角类:
1.支持静态文件配置属性,
2.支持动态代码改圆角率,
3.支持所有的控件而不是图片控件
完整的代码如下:
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.TextView;
import com.xxx.demo.R;
/**
* Created by xxx on 2019/1/27.
*/
public class RoundTextView extends TextView {
Paint outPaint;
int paintColor=Color.WHITE,tvRadio=21;
Path path1,path2;
RectF outRect;
public RoundTextView(Context context) {
super(context);
initPaint(context, null);
}
public RoundTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint(context, attrs);
}
public RoundTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
initPaint(context, attrs);
}
private void initPaint(Context context, AttributeSet attrs) {
//自定义属性
//outPaint的颜色值 ,圆角率
if (attrs!=null) {
TypedArray ta= context.obtainStyledAttributes(attrs, R.styleable.RoundTextView);
paintColor = ta.getColor(R.styleable.RoundTextView_paintColor, Color.WHITE);
tvRadio= ta.getDimensionPixelSize(R.styleable.RoundTextView_tvRadio,21);
ta.recycle();
}
if(outPaint==null){
outPaint = new Paint();
outPaint.setStyle(Paint.Style.FILL_AND_STROKE);
outPaint.setAntiAlias(true);
outPaint.setColor(paintColor);
}
if (path1==null) {
path1 = new Path();
path2 = new Path();
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
outRect=new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight());
}
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
path1.reset();
path2.reset();
path1.addRect(outRect,Path.Direction.CW);
path2.addRoundRect(outRect,tvRadio,tvRadio,Path.Direction.CW);
if (Build.VERSION.SDK_INT >= 19) {
path1.op(path2, Path.Op.DIFFERENCE );
}
canvas.drawPath(path1, outPaint);
canvas.restore();
super.onDraw(canvas);
}
public void setRadio(int radio) {
tvRadio = radio;
requestLayout();
}
public void setColor(int color){
if (outPaint!=null) {
outPaint.setColor(color);
}
requestLayout();
}
/**
* @param color;#ff0000
*/
public void setColor(String color){
if (outPaint!=null) {
outPaint.setColor(Color. parseColor(color));
}
requestLayout();
}
}
在res–>values–>attrs自定义属性的代码如下:
在布局文件中使用如下:
注意这里使用了app命名空间,记得加这句话
xmlns:app=“http://schemas.android.com/apk/res-auto”
实现效果如下:
说明:
1,把红色设置成圆角控件的背景颜色,就可以看起来是圆角
2,实现的原理是:在要实现圆角控件的上面放一个遮住4个角的控件,而4个角的控件是通过path.addXXX然后取2个path的交集或者并集而得到的(其实利用path.op可以得到很多好玩的图形 path1.op(path2, Path.Op.DIFFERENCE,具体可自行百度 );