Android自定义圆形图片

最近研究了一下圆形图片控件,之前一直是用别人写好的类,自己写一下,发现对canvas理解更深入了。

基本思路:
自定义CircleImageView继承自ImageView,在canvas中新建一个图层,先把要显示的头像绘制在上面,再绘制圆形遮罩,设置画笔模式为:当两个图像重叠时,显示交叉部分下面的图像。

源码如下:(直接拿去用就可以了)

package com.lt.DrawDemo;

import android.content.Context;
import android.graphics.*;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class CircleImageView extends ImageView {

    private Paint mPaint;
    private Xfermode xfermode;

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

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

    public void init() {
        //两层交集 显示下层
        xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setFilterBitmap(false);
        mPaint.setXfermode(xfermode);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        //这个地方一定要屏蔽
        //super.onDraw(canvas);
        //记录当前图层
        int count = canvas.getSaveCount();
        //新建一个图层
        canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
        //画出背景图片,即我们要设置的头像,可能是正方形或长方形
        Drawable drawable = getDrawable();
        drawable.setBounds(0, 0, getWidth(), getHeight());
        drawable.draw(canvas);
        //画出圆形遮罩
        canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/2,mPaint);
        //返回到之前的图层,并把在该图层绘制的图像复制到那个图层。
        canvas.restoreToCount(count);
        return;
    }
}

在看下面源码之前,你需要先明白以下几个方面:
1.Xfermode
/**
* Xfermode is the base class for objects that are called to implement custom
* “transfer-modes” in the drawing pipeline. The static function Create(Modes)
* can be called to return an instance of any of the predefined subclasses as
* specified in the Modes enum. When an Xfermode is assigned to an Paint, then
* objects drawn with that paint have the xfermode applied.
*/
Xfermode有三个子类,分别是:
AvoidXfermode : 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。
PixelXorXfermode : 当覆盖已有的颜色时,应用一个简单的像素异或操作。
PorterDuffXfermode : 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。

在项目中,我们定义了:
private Xfermode xfermode;
//当两个图像重叠时,显示重叠部分的下方图像。
xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
//当给mPaint设置Xfernode属性后,绘制两个图像时,就会显示重叠部分下方的图案。
mPaint.setXfermode(xfermode);
2.onDraw中要注释掉super.onDraw(canvas);
这是因为在ImageView的onDraw中,他自己会去绘制我们设置的src图片。而我们不希望他去绘制。
3.关于如何创建layer以及layer的回滚
1. canvas是一张画布,我们所画的,如drawCircle(),drawText()等,都是画在canvas上面的;
2. 一个canvas上面可以有多个layer。可以使用saveLayer, savaLayerAlpha来新建一个layer;可以使用restore,restoreToCount来回到第几个图层。其中,图层是通过“栈”来管理的。
3. 关于canvas与layer具体可参考:
http://blog.sina.com.cn/s/blog_6e51958501013b62.html
http://blog.csdn.net/linghu_java/article/details/8939952
4.demo下载地址
http://download.csdn.net/detail/qq_23936173/9515780

你可能感兴趣的:(android,imageview)