标签:
最近研究了一下圆形图片控件,之前一直是用别人写好的类,自己写一下,发现对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
标签:
原文地址:http://blog.csdn.net/qq_23936173/article/details/51364993