製作圓形頭像

生活中我們見到的大多數頭像都變成圓形頭像,因爲圓形可以給客戶一種親和感,更能被客戶接受。而我們Android5.0之前,想要使用圓形頭像必須要自己來手寫,5.0之後自帶了圓形頭像爲我們開發人員剩了好多事情。
閒話不多說了,直接來看一下效果。
這裏寫圖片描述
實現分爲下面幾步:
1.自定義屬性(attr.xml);
2.構造方法中獲取屬性值;
3.調用ondraw()方法;
具體的實現步驟:
1.獲取圖片

 @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        mBitmap = bm;
        setup();
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
        mBitmap = getBitmapFromDrawable(drawable);
        setup();
    }

    @Override
    public void setImageResource(@DrawableRes int resId) {
        super.setImageResource(resId);
        mBitmap = getBitmapFromDrawable(getDrawable());
        setup();
    }

    @Override
    public void setImageURI(Uri uri) {
        super.setImageURI(uri);
        mBitmap = getBitmapFromDrawable(getDrawable());
        setup();
    }

2.方法中調用了setup()方法

if (!mReady) {
            mSetupPending = true;
            return;
        }

因爲mReady默認是false的,所以只會執行前面的這一句就結束了。
3.調用構造方法獲取屬性值

public CircleImageView(Context context) {
        super(context);

        init();
    }

    public CircleImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
//屬性數組
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);

        mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
        mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);
        mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_border_overlay, DEFAULT_BORDER_OVERLAY);
//回收數組
        a.recycle();
//調用init()方法
        init();
    }

4.調用init()方法

private void init() {
        super.setScaleType(SCALE_TYPE);
        mReady = true;
//執行完setup()方法的前面部分,mSetupPending已經變成了true
        if (mSetupPending) {
            setup();
            mSetupPending = false;
        }
    }

init()方法的作用只是一用來調節執行順序的,因爲一定要控制先執行構造方法拿到數據之後,然後再去執行setup()方法中的有效部分設置數據。
5.調用setup()方法中的有效部分

private void setup() {
//第一次執行只能執行到這個地方
        if (!mReady) {
            mSetupPending = true;
            return;
        }

        if (mBitmap == null) {
            return;
        }
//初始化一個圖片渲染器,渲染器
        mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//設置圖片畫筆
        mBitmapPaint.setAntiAlias(true);
        mBitmapPaint.setShader(mBitmapShader);
//設置描邊畫筆
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(mBorderColor);
        mBorderPaint.setStrokeWidth(mBorderWidth);
//獲取圖片的高度
        mBitmapHeight = mBitmap.getHeight();
        mBitmapWidth = mBitmap.getWidth();
//創建一個大小和這個view一樣大的矩形框
        mBorderRect.set(0, 0, getWidth(), getHeight());
//計算外邊半徑(畫圓的時候會用到,外邊框的中間處)
        mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2);

        mDrawableRect.set(mBorderRect);
        if (!mBorderOverlay) {
        //控制mDrawableRect比mBorderRect邊距空有mBorderWidth
            mDrawableRect.inset(mBorderWidth, mBorderWidth);
        }
        mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);

        updateShaderMatrix();
        invalidate();
    }

6.調用updateShaderMatrix()方法,用來優化繪製的效果

private void updateShaderMatrix() {
        float scale;
        float dx = 0;
        float dy = 0;

        mShaderMatrix.set(null);
//比較是按照寬來縮放還是按照長來縮放
        if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
            scale = mDrawableRect.height() / (float) mBitmapHeight;
            dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
        } else {
            scale = mDrawableRect.width() / (float) mBitmapWidth;
            dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
        }
//mShaderMatrix對象用來對圖片進行變換
        mShaderMatrix.setScale(scale, scale);
        mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);

        mBitmapShader.setLocalMatrix(mShaderMatrix);
    }

7.執行invalidate()方法,進行繪製頭像

@Override
    protected void onDraw(Canvas canvas) {
        if (getDrawable() == null) {
            return;
        }

        canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
        if (mBorderWidth != 0) {
            canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
        }
    }
發佈了37 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章