1. 程式人生 > >Android自定義控制元件打造放大鏡效果

Android自定義控制元件打造放大鏡效果

      上週沒啥事,想到以前看到過一個放大鏡的效果,雖然感覺這個效果沒什麼用,但是覺得還是挺酷炫的,所以就花了點時間,做了一個放大鏡的自定義控制元件。

       首先說說我的思路,需要做到放大效果,我的想法是利用矩陣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);
        }
    }

       這樣放大鏡的自定義控制元件基本完成了,講的可能不是很詳細,具體還是閱讀原始碼理解的更深刻,原始碼傳送門點選連結

最後實現效果如下: