一个简单的自定义CircleDrawable,实现圆形头像效果

Github上有一个star5000+的CircleImageView,代码设计得十分简洁流畅,其实通过自定义一个Drawable也完全可以实现这个效果。(ps:其实是今天在看源码的时候,在Setting模块看到了一个类似的CircleFramedDrawable~,自己几乎没有修改就能实现圆形图片的效果)。

因为代码十分简单,所以一些简单分析就直接写在注释里了。这里只说一下实现思路:通过为画笔设置PorterDuff.Mode,来让新建的圆形图层与原Bitmap只显示重合部分。(PorterDuff.Mode:一个强大的图像转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。哈哈,说人话就是用来控制图层与图层之间如何覆盖,覆盖之后取哪部分显示到画布上,有兴趣的可以自行百度,这里只用到了两种模式。)

下面直接上代码和效果图:

在构造方法里处理图层关系:
    public CircleFramedDrawable(Bitmap icon, int size) {
        super();
        mSize = size;

        mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(mBitmap);

        final int width = icon.getWidth();
        final int height = icon.getHeight();
        final int square = Math.min(width, height);

        final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square);
        final RectF circleRect = new RectF(0f, 0f, mSize, mSize);

        final Path fillPath = new Path();
        //path.addArc方法用于绘制圆弧,这个圆弧取自RectF矩形的内接椭圆上的一部分,圆弧长度由后两个角度参数决定
        fillPath.addArc(circleRect, 0f, 360f);
        //PorterDuff.Mode.CLEAR:清除画布(所绘制不会提交到画布上)
        canvas.drawColor(0, PorterDuff.Mode.CLEAR);

        // opaque circle matte
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawPath(fillPath, mPaint);

        // mask in the icon where the bitmap is opaque(不透明)
        //PorterDuff.Mode.SRC_IN:两者相交的地方绘制源图
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(icon, cropRect, circleRect, mPaint);

        // prepare paint for frame drawing
        // 别忘记还原画笔~
        mPaint.setXfermode(null);

        mScale = 1f;

        mSrcRect = new Rect(0, 0, mSize, mSize);
        mDstRect = new RectF(0, 0, mSize, mSize);
    }

当然支持图片的缩放啦:
    @Override
    public void draw(Canvas canvas) {
        //缩放处理
        final float inside = mScale * mSize;
        final float pad = (mSize - inside) / 2f;
        //将矩形的坐标设置为缩放后指定的值
        mDstRect.set(pad, pad, mSize - pad, mSize - pad);
        //第一个mSrcRect代表要绘制的bitmap区域,第二个mDstRect代表的是要将bitmap绘制在屏幕的什么地方
        canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
    }
获取drawable时传入我们想要的大小就可以了
    public static CircleFramedDrawable getInstance(Context context, Bitmap icon,float size) {
        Resources res = context.getResources();
        float iconSize = px2dip(context,size);
        CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
        return instance;
    }
怎么使用?
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
                R.drawable.workingdog);
        mIcon.setImageDrawable(CircleFramedDrawable.getInstance(this,bitmap,800));
    }

所以可以不用修改项目中的布局文件,直接加一个Drawable类就能在任何时候转换图片至圆形了!

效果图:

__*

Demo地址

你可能感兴趣的:(一个简单的自定义CircleDrawable,实现圆形头像效果)