前段时间学习了一下自定义View,再加上最近需要一个圆角ImageView就翻了翻CSDN,就这么给我翻到了一篇(来源见末尾),看了看觉得蛮简单的就在其基础上做了点修改,然后占为己有了!
思路
1.继承AppCompatImageView(不知道为什么无法继承ImageView,但无大碍)。
2.用Bitmap绘图。
3.在ImageView的四角绘制遮罩。
效果
代码
一、初始化
1.获取自定义属性参数值
在values文件夹下创建attr.xml,在里面设置自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ECornerImageView">
<attr name="cornerWidth" format="dimension" />
<attr name="cornerHeight" format="dimension" />
<attr name="cornerRadius" format="dimension" />
</declare-styleable>
</resources>
获取自定义属性
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes
(attrs, R.styleable.ECornerImageView);
cornerWidth = a.getDimensionPixelSize
(R.styleable.ECornerImageView_cornerWidth, cornerWidth);
cornerHeight = a.getDimensionPixelSize
(R.styleable.ECornerImageView_cornerHeight, cornerHeight);
Log.d(TAG,"cornerWidth:"+cornerWidth);
Log.d(TAG,"cornerHeight:"+cornerHeight);
cornerRadius = a.getDimensionPixelSize
(R.styleable.ECornerImageView_cornerRadius, cornerRadius);
Log.d(TAG,"cornerRadius:"+cornerRadius);
if (cornerRadius!=-1){
cornerHeight = cornerRadius;
cornerWidth = cornerRadius;
}
Log.d(TAG,"cornerWidth2:"+cornerWidth);
Log.d(TAG,"cornerHeight2:"+cornerHeight);
//回收
a.recycle();
} else {
cornerWidth = CORNERWIDTH;
cornerHeight = CORNERHEIGHT;
}
2.Path和Paint
path = new Path();
cornerPaint = new Paint();
cornerPaint.setColor(Color.WHITE);
cornerPaint.setAntiAlias(true);
cornerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
bitPaint = new Paint();
二、绘制
public void draw(Canvas canvas) {
/*绘制图片
界面显示图片时,需要的内存空间是按像素点的多少乘以每个像素点占用的空间大小来
计算的。
* Bitmap.Config ARGB_8888:每个像素占四位,即A=8,R=8,G=8,B=8,那么一个
像素点占8+8+8+8=32位*/
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
Bitmap.Config.ARGB_8888);
Canvas cornerCanvas = new Canvas(bitmap);
super.draw(cornerCanvas);
/*绘制圆角遮罩*/
if (leftTop){
drawLeftTop(cornerCanvas);
}
if (lefBottom){
drawLeftBottom(cornerCanvas);
}
if (rightTop){
drawRightTop(cornerCanvas);
}
if (rightBottom){
drawRightBottom(cornerCanvas);
}
canvas.drawBitmap(bitmap, 0, 0, bitPaint);
//bitPaint.setXfermode(null);
/*在Android应用里,最耗费内存的就是图片资源。而且在Android系统中,读取位图Bitmap时,
分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常。*/
if(bitmap != null && !bitmap.isRecycled()){
// 回收bitmap并且置为null
bitmap.recycle();
bitmap = null;
}
/*通知垃圾回收器尽快进行回收*/
System.gc();
}
三、边角的遮罩绘制
用path绘制遮罩,先画竖线,再画横线,最后画椭圆形的弧线。如图红线所示。
/*绘制左上角圆角遮罩*/
private void drawLeftTop(Canvas canvas) {
/*绘制横竖两条直线*/
path.moveTo(0, cornerHeight);
path.lineTo(0, 0);
path.lineTo(cornerWidth, 0);
/*绘制椭圆的弧线*/
path.arcTo(new RectF(0, 0, cornerWidth * 2, cornerHeight * 2), -90, -90);
path.close();
canvas.drawPath(path, cornerPaint);
}
/*绘制左下角圆角遮罩*/
private void drawLeftBottom(Canvas canvas) {
/*绘制横竖两条直线*/
path.moveTo(0, getHeight() - cornerHeight);
path.lineTo(0, getHeight());
path.lineTo(cornerWidth, getHeight());
/*绘制椭圆的弧线*/
path.arcTo(new RectF(0, getHeight() - cornerHeight * 2, cornerWidth * 2, getHeight()), 90, 90);
path.close();
canvas.drawPath(path, cornerPaint);
}
/*绘制右上角圆角遮罩*/
private void drawRightBottom(Canvas canvas) {
/*绘制横竖两条直线*/
path.moveTo(getWidth() - cornerWidth, getHeight());
path.lineTo(getWidth(), getHeight());
path.lineTo(getWidth(), getHeight() - cornerHeight);
/*绘制椭圆的弧线*/
path.arcTo(new RectF(getWidth() - cornerWidth * 2, getHeight() - cornerHeight * 2, getWidth(), getHeight()), -0, 90);
path.close();
canvas.drawPath(path, cornerPaint);
}
/*绘制右下角圆角遮罩*/
private void drawRightTop(Canvas canvas) {
/*绘制横竖两条直线*/
path.moveTo(getWidth(), cornerHeight);
path.lineTo(getWidth(), 0);
path.lineTo(getWidth() - cornerWidth, 0);
/*绘制椭圆的弧线*/
path.arcTo(new RectF(getWidth() - cornerWidth * 2, 0, getWidth(), 0 + cornerHeight * 2), -90, 90);
path.close();
canvas.drawPath(path, cornerPaint);
}
使用
1.依赖
allprojects {
repositories {
...
maven { url 'https://www.jitpack.io' }
}
}
dependencies {
implementation 'com.github.Mils-liu:ECornerImageView:v1.0.0'
}
2.布局
cornerRadius为边角的半径,会覆盖cornerHeight和cornerWidth的值
3.动态设置
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
eImg = (ECornerImageView)findViewById(R.id.eimg);
//设置哪个角为椭圆角,分别为左上,左下,右上,右下
eImg.setCorner(false,true,true,false);
//设置圆角半径,单位为dp,会覆盖椭圆角的宽高
eImg.setRadius(40);
//设置椭圆角的高,单位为dp
eImg.setcornerHeight(40);
//设置椭圆角的宽,单位为dp
eImg.setcornerWidth(80);
}
END
github地址:https://github.com/Mils-liu/ECornerImageView
来源:《android imageview 设置圆角》
链接:https://blog.csdn.net/why_111/article/details/80720043
来源:《android中path的arcTo方法的使用》
链接:https://blog.csdn.net/whyrjj3/article/details/7940385