由於最近工(lan)作(ai)太(wan)忙(qi),已經好久沒有更新過文章了,爲了防止自己徹底殘廢,決定先擼一個簡單的萬能圓形控件練練手。
圖片控件首先想到的肯定是ImageView,所以我就在ImageView基礎上實現圓形控件,這樣做有兩個好處,第一可以直接使用系統提供的非常Nice的方法和效果,另一個就可在使用Glide 的時候可以保持隊形,不用專門在寫一個Glide加載圓形圖片的方法了。
老規矩,線上效果圖片:
首先我們先繼承 AppCompatImageView 控件,自定義控件離不開onMeasure,onLayout,onDraw 三大法寶,不過由於系統已經進行過處理,這裏就不需要在處理onMearch,onLayout兩個方法了,只需要重寫onDraw 方法即可;
這裏通過Xfermodes方法實現圓形圖片,這張圖片顯示了Xfermodes的16中效果,我這裏選用 DST_IN 實現;
剩下的貼上onDrown方法代碼
@Override
protected void onDraw(Canvas canvas) {
setLayerType(LAYER_TYPE_HARDWARE, mPaint);
canvas.save();
super.onDraw(canvas);
mPaint.setXfermode(xfermode);
mPaint.setStyle(Paint.Style.FILL);
//更改path
initRadios(getWidth(), getHeight(), borderPath, borderWidth / 2);
canvas.drawPath(borderPath, mPaint);
mPaint.setXfermode(null);
//是否繪製邊框
if (showBorder) {
mPaint.setStrokeWidth(borderWidth);
mPaint.setColor(borderColor);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawPath(borderPath, mPaint);
}
canvas.restore();
}
上述代碼中 initRadios(getWidth(), getHeight(), borderPath, borderWidth /2); 是用來更改path的方法,通過不斷的更改path來更改圖片形狀
private void initRadios(int w, int h, Path borderPath, int borderWidth) {
borderPath.reset();
int left = (int) Math.ceil(borderWidth);
int top = (int) Math.ceil(borderWidth);
int right = (int) Math.ceil(w - borderWidth);
int bottom = (int) Math.ceil(h - borderWidth);
//左上
borderPath.moveTo(left, top +radiusLeftTop);
rectLeftTop.left = left;
rectLeftTop.top = top;
rectLeftTop.right =radiusLeftTop *2 + left;
rectLeftTop.bottom = top +radiusLeftTop *2;
borderPath.arcTo(rectLeftTop, 180, 90);
//右上
borderPath.lineTo(right -radiusRightTop, top);
rectRightTop.left = right -radiusRightTop *2;
rectRightTop.top = top;
rectRightTop.right = right;
rectRightTop.bottom = top +radiusRightTop *2;
borderPath.arcTo(rectRightTop, 270, 90);
//
// //右下
borderPath.lineTo(right, bottom -radiusRightBottom);
rectRightBottom.left = right -radiusRightBottom *2;
rectRightBottom.top = bottom -radiusRightBottom *2;
rectRightBottom.right = right;
rectRightBottom.bottom = bottom;
borderPath.arcTo(rectRightBottom, 360, 90);
//
// //左下
borderPath.lineTo(left +radiusLeftBottom, bottom);
rectLeftBottom.left = left;
rectLeftBottom.top = bottom -radiusLeftBottom *2;
rectLeftBottom.right =radiusLeftBottom *2 + left;
rectLeftBottom.bottom = bottom;
borderPath.arcTo(rectLeftBottom, 90, 90);
borderPath.lineTo(left, top +radiusLeftTop);
borderPath.close();
}
到這裏基本主要功能已經實現了,剩下只是一些初始化代碼的工具,需要的可以自己下載 源碼 看一下
最下邊的長圖片時一個繼承自Fragment的ViewGroup,可以實現圓角佈局,原理是一樣的,只需要重寫dispatchDraw 方法即可