自己動手兩分鐘擼一個萬能圓形控件

由於最近工(lan)作(ai)太(wan)忙(qi),已經好久沒有更新過文章了,爲了防止自己徹底殘廢,決定先擼一個簡單的萬能圓形控件練練手。

圖片控件首先想到的肯定是ImageView,所以我就在ImageView基礎上實現圓形控件,這樣做有兩個好處,第一可以直接使用系統提供的非常Nice的方法和效果,另一個就可在使用Glide 的時候可以保持隊形,不用專門在寫一個Glide加載圓形圖片的方法了。

老規矩,線上效果圖片:

image

首先我們先繼承 AppCompatImageView 控件,自定義控件離不開onMeasure,onLayout,onDraw 三大法寶,不過由於系統已經進行過處理,這裏就不需要在處理onMearch,onLayout兩個方法了,只需要重寫onDraw 方法即可;

這裏通過Xfermodes方法實現圓形圖片,這張圖片顯示了Xfermodes的16中效果,我這裏選用 DST_IN 實現;

image

剩下的貼上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 方法即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章