使用BitmapShader显示圆形头像

对于一些应用app特别是社交app中,通常需要用户登陆后显示一个圆形的头像作为用户的标识。普通的ImageView是不可以实现这个功能的,那么怎么才能画出一个圆形头像呢?BitmapShader可以帮我们解决这个问题。
首先来看看BitmapShader的定义,如下:

Shader used to draw a bitmap as a texture. The bitmap can be repeated or mirrored by setting the tiling mode.

着色器(shader)用于将bitmap作为纹理绘制到画布上,超出bitmap的部分根据不同的mode作出不同的绘制要求。

CLAP 渲染器超出原始的位置,将会取边缘的颜色绘制
MIRROR 以镜像的方式平铺
REPEAT 横向和纵向重复渲染,类似与平铺



生成BitmapShader的实例之后,就可以使用paint.setShader(shader)设置paint中将要画的bitmap。所以最后还是通过canvas的drawCircle来完成我们的需求的。

package com.app.motion.bitmapshadermotion.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * Created by joe.wang on 2016/9/12.
 */
public class PhotoImageView extends ImageView {

    private int mWdith;
    private int mHeight;
    private Paint mPaint;
    private BitmapShader mBitmapShader;
    private Bitmap mBitmap;
    private Rect mDrawableRect;
    private Matrix mShaderMartix;

    public PhotoImageView(Context context) {
        this(context, null);
    }

    public PhotoImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        mShaderMartix = new Matrix();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWdith = w;
        mHeight = h;
        fillDrawableRect();
        setup();
    }

    private void setup() {
        if (mBitmap == null) {
            getDrawableBitmap();
        }
    }

    /**
     * 获取当前设置的android:src属性中的图片bitmap
     */
    private void getDrawableBitmap() {
        if (getDrawable() == null) {
            return;
        } else {
            Drawable d = getDrawable();
            Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            d.draw(canvas);
            mBitmap = bitmap;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mBitmap == null) {
            super.onDraw(canvas);
        } else {
            getDrawableBitmap();
            mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            updateShaderMatrix();
            mPaint.setShader(mBitmapShader);
            canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRect.width() / 2, mPaint);
        }
    }

    /**
     * 获取一个正方形,用于绘制圆形
     */
    private void fillDrawableRect() {
        int avaliableWidth = mWdith - getPaddingLeft() - getPaddingRight();
        int avaliableHeight = mHeight - getPaddingTop() - getPaddingBottom();
        int slideLength = Math.min(avaliableWidth, avaliableHeight);
        int top = getPaddingTop() + (avaliableHeight - slideLength) / 2;
        int left = getPaddingLeft() + (avaliableWidth - slideLength) / 2;
        mDrawableRect = new Rect(left, top, left + slideLength, top + slideLength);
    }

    /**
     * 根据不同的比例大小设置bitmap的缩放大小和偏移量
     */
    private void updateShaderMatrix() {
        float scale = 0;
        int dx = 0;
        int dy = 0;
        if (mBitmap.getWidth() * mDrawableRect.height() > mBitmap.getHeight() * mDrawableRect.width()) {
            scale = mDrawableRect.width() * 1.0f / mBitmap.getWidth();
            dy = (int) ((mDrawableRect.height() - mBitmap.getHeight() * scale) * 0.5f);
        } else {
            scale = mDrawableRect.height() * 1.0f / mBitmap.getHeight();
            dx = (int) ((mDrawableRect.width() - mBitmap.getWidth() * scale) * 0.5f);
        }
        mShaderMartix.setScale(scale, scale);
        mShaderMartix.postTranslate(dx + mDrawableRect.left, dy + mDrawableRect.top);
        mBitmapShader.setLocalMatrix(mShaderMartix);
    }
}

这里写图片描述

posted @ 2016-09-13 00:29  豌豆豆  阅读(168)  评论(0编辑  收藏  举报