上周没啥事,想到以前看到过一个放大镜的效果,虽然感觉这个效果没什么用,但是觉得还是挺酷炫的,所以就花了点时间,做了一个放大镜的自定义控件。
首先说说我的思路,需要做到放大效果,我的想法是利用矩阵Matrix将图片进行放大和平移,然后再根据放大镜显示的位置,显示对应的放大位置。所以步骤如下:
先做一个可以跟随手指移动的控件,重写onTouchEvent方法,代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK )
{
case MotionEvent.ACTION_DOWN:
locationX = getX();
locationY = getY();
downX = event.getRawX();
downY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE://随手移动,getRawX()与getX()有区别
setX(locationX+(event.getRawX()-downX));
setY(locationY+(event.getRawY()-downY));
invalidate();
break;
}
return true;
}
这样控件就会跟随手指的移动而移动,然后移动的时候,利用invalidate()放大调用onDraw方法进行画图绘制。onDraw里绘制了放大镜的底层背景,中间显示的放大图片,已经上层的滤镜效果。代码如下:
@Override
protected void onDraw(Canvas canvas) {
if(bm!=null)
{
Paint paintBg = new Paint();//背景防止加载自带透明的图片时,放大图片后面能看到原来的图片
paintBg.setAntiAlias(true);//抗锯齿
paintBg.setColor(Color.parseColor("#ffffff"));
canvas.drawCircle(magnifierLen/2,magnifierLen/2,magnifierLen/2,paintBg);
Paint paint = new Paint();
paint.setAntiAlias(true);//抗锯齿
paint.setShader(bitmapShader);//bitmapShader画圆形图片
//创建矩阵,缩放平移图片
Matrix matrix = new Matrix();
matrix.setScale(scaleX, scaleY);
matrix.postTranslate(-(scaleX*getX()+(scaleX-1)*magnifierLen/2), -(scaleY*getY()+(scaleY-1)*magnifierLen/2));//为了放大效果是取放大镜中心开始放大的效果
bitmapShader.setLocalMatrix(matrix);//利用bitmapShader画圆形图片
canvas.drawCircle(magnifierLen/2,magnifierLen/2,magnifierLen/2,paint);
Paint paintShade = new Paint();//外层遮罩
paintShade.setAntiAlias(true);//抗锯齿
paintShade.setColor(Color.parseColor(magnifierColor));
paintShade.setAlpha(magnifierAlpha);
canvas.drawCircle(magnifierLen/2,magnifierLen/2,magnifierLen/2,paintShade);
}
}
这样核心代码就完成了,然后中间需要用到很多可配置的设置,比如放大镜的初始位置,初始大小,放大倍数,初始滤镜的透明度等等。于是我们创建一个创建者,用于构造放大镜实例,代码如下:
/**
* 创建建造者,用于构建当前对象。多用于复杂构建
*/
public static class Builder
{
private Context context;
private int initLeft=0,initTop=0;//初始位置,相对于父控件的位置
private int viewW=300,viewH=300;//控件宽高
private float scaleX=1.5f,scaleY=1.5f;//x,y的放大倍数
private String magnifierColor = "#ff0000";//放大镜颜色
private int magnifierAlpha = 32;//放大镜透明度
private ViewGroup rootVg;
public Builder(Context context) {
this.context = context;
}
public Builder intiLT(int initLeft,int initTop)
{
if(initLeft>0)
this.initLeft = initLeft;
if(initTop>0)
this.initTop = initTop;
return this;
}
public Builder viewWH(int viewW,int viewH)
{
this.viewW = viewW;
this.viewH = viewH;
return this;
}
public Builder rootVg(ViewGroup rootVg)
{
this.rootVg = rootVg;
return this;
}
public Builder scale(float scale)//放大镜放大倍数
{
this.scaleX = scale;
this.scaleY = scale;
return this;
}
public Builder color(String color)
{
this.magnifierColor = color;
return this;
}
public Builder alpha(int alpha)
{
if(alpha>=200)
{
this.magnifierAlpha = 200;
}
else if(alpha<0)
{
this.magnifierAlpha = 0;
}
else
{
this.magnifierAlpha = alpha;
}
return this;
}
public MagnifierView build()
{
return new MagnifierView(this,context);
}
}
这样放大镜的自定义控件基本完成了,讲的可能不是很详细,具体还是阅读源码理解的更深刻,源码传送门点击链接。