上周沒啥事,想到以前看到過一個放大鏡的效果,雖然感覺這個效果沒什麼用,但是覺得還是挺酷炫的,是以就花了點時間,做了一個放大鏡的自定義控件。
首先說說我的思路,需要做到放大效果,我的想法是利用矩陣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);
}
}
這樣放大鏡的自定義控件基本完成了,講的可能不是很詳細,具體還是閱讀源碼了解的更深刻,源碼傳送門點選連結。
最後實作效果如下: