強力なグラフィックボード(2)


            :[    ](http://blog.csdn.net/songhengqian/article/details/51792420)           ,                 。
              ,            ,        ,                ,           (           ,  )。                     ,           ,            , onSizeChanged()     :
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

        if (bitmap_bg==null){
            bitmap_bg=Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_4444);
            Drawable drawable=getResources().getDrawable(R.drawable.p1);
            BitmapDrawable bitmapDrawable= (BitmapDrawable) drawable;
            bitmap_bg= bitmapDrawable.getBitmap();
            bitmapWidth= bitmap_bg.getWidth();
            bitmapHeight=bitmap_bg.getHeight();
        mBitmapBgmMatix.postScale(scaleX,scaleY);
        }
        if (bitmap_fg == null && bitmap_bg!=null) {
            bitmap_fg=Bitmap.createBitmap(bitmapWidth,bitmapHeight, Bitmap.Config.ARGB_4444);
            //             
            bitmap_fg.eraseColor(Color.alpha(0));
            mCanvas=new Canvas(bitmap_fg);//  mCanvas          mBitmap 
            mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            sourceBitmap=bitmap_fg;
        }
    }

将来性のバックグラウンドを同期し、必要な変数定数を宣言しましょう.
 /**
     *        
     */
    public static final int STATUS_INIT = 1;

    /**
     *         
     */
    public static final int STATUS_ZOOM_OUT = 2;

    /**
     *         
     */
    public static final int STATUS_ZOOM_IN = 3;
    /**
     *          ,    STATUS_INIT、STATUS_ZOOM_OUT、STATUS_ZOOM_IN STATUS_MOVE
     */
    private int currentStatus;
 //       
    private Bitmap sourceBitmap;
    //        
    private int width;
    private int height;

    /**
     *               
     */
    private float totalTranslateX;

    /**
     *               
     */
    private float totalTranslateY;

    /**
     *               
     */
    private float totalRatio;

    /**
     *                  
     */
    private float scaledRatio;

    /**
     *              
     */
    private float initRatio;
    /**
     *          ,      ,        
     */
    private float currentBitmapWidth;

    /**
     *          ,      ,        
     */
    private float currentBitmapHeight;
    /**
     *             ,        
     */
    private float centerPointX;

    /**
     *             ,        
     */
    private float centerPointY;

    /**
     *                 
     */
    private float movedDistanceX;

    /**
     *                 
     */
    private float movedDistanceY;
    /**
     *              
     */
    private float lastXMove = -1;

    /**
     *              
     */
    private float lastYMove = -1;
    /**
     *            
     */
    private double lastFingerDis;

インタフェースを初期化するには、画像の中央表示を保証する必要があります.
   /**
     *           ,       ,                   。
     *
     * @param canvas
     */
    private void initBitmap(Canvas canvas) {
        if (sourceBitmap != null) {
            mMatrix.reset();
            int bitmapWidth = sourceBitmap.getWidth();
            int bitmapHeight = sourceBitmap.getHeight();

            if (bitmapWidth > width || bitmapHeight > height) {

                if (bitmapWidth - width > bitmapHeight - height) {
                    //             ,        ,          
                    float ratio = width / (bitmapWidth * 1.0f);
                    mMatrix.postScale(ratio, ratio);
                    float translateY = (height - (bitmapHeight * ratio)) / 2f;
                    //            ,         
                    mMatrix.postTranslate(0, translateY);
                    totalTranslateY = translateY;
                    totalRatio = initRatio = ratio;
                } else {
                    //             ,        ,          
                    float ratio = height / (bitmapHeight * 1.0f);
                    mMatrix.postScale(ratio, ratio);
                    float translateX = (width - (bitmapWidth * ratio)) / 2f;
                    //            ,         
                    mMatrix.postTranslate(translateX, 0);
                    totalTranslateX = translateX;
                    totalRatio = initRatio = ratio;
                }
                currentBitmapWidth = bitmapWidth * initRatio;
                currentBitmapHeight = bitmapHeight * initRatio;
            } else {
                //               ,         
                float translateX = (width - sourceBitmap.getWidth()) / 2f;
                float translateY = (height - sourceBitmap.getHeight()) / 2f;

                mMatrix.postTranslate(translateX, translateY);
                totalTranslateX = translateX;
                totalTranslateY = translateY;
                totalRatio = initRatio = 1f;
                currentBitmapWidth = bitmapWidth;
                currentBitmapHeight = bitmapHeight;
            }
            canvas.drawBitmap(bitmap_bg, mMatrix, mPaint);
            canvas.drawBitmap(sourceBitmap, mMatrix, mPaint);
        }
    }

インタフェースの初期化が完了すると、スケールの平行移動を開始できます.
   /**
     *          。
     *
     * @param canvas
     */
    private void scale(Canvas canvas) {
        mMatrix.reset();

        //              
        mMatrix.postScale(totalRatio, totalRatio);
        float scaledWidth = sourceBitmap.getWidth() * totalRatio;
        float scaledHeight = sourceBitmap.getHeight() * totalRatio;
        float translateX = 0f;
        float translateY = 0f;
        //               ,                。                   
        if (currentBitmapWidth < width) {
            translateX = (width - scaledWidth) / 2f;
        } else {
            translateX = totalTranslateX * scaledRatio + centerPointX * (1 - scaledRatio);

            //       ,                    
            if (translateX > 0) {
                translateX = 0;

            } else if (width - translateX > scaledWidth) {
                translateX = width - scaledWidth;
                Log.e(TAG, "translateX......" + translateX);
                Log.e(TAG, "scaledWidth....." + scaledWidth);
            }
        }

        //               ,                。                   
        if (currentBitmapHeight < height) {
            translateY = (height - scaledHeight) / 2f;

        } else {

            translateY = totalTranslateY * scaledRatio + centerPointY * (1 - scaledRatio);
            //       ,                    
            if (translateY > 0) {
                translateY = 0;
            } else if (height - translateY > scaledHeight) {
                translateY = height - scaledHeight;

            }
        }

        //           ,             
        mMatrix.postTranslate(translateX, translateY);
        totalTranslateX = translateX;
        totalTranslateY = translateY;
        currentBitmapWidth = scaledWidth;
        currentBitmapHeight = scaledHeight;
        canvas.drawBitmap(bitmap_bg, mMatrix, mPaint);
        canvas.drawBitmap(sourceBitmap, mMatrix, mPaint);
    }

    /**
     *          
     *
     * @param canvas
     */
    private void translate(Canvas canvas) {
        mMatrix.reset();
        //                 
        float translateX = totalTranslateX + movedDistanceX;
        float translateY = totalTranslateY + movedDistanceY;
        //                  
        mMatrix.postScale(totalRatio, totalRatio);
        //            
        mMatrix.postTranslate(translateX, translateY);
        totalTranslateX = translateX;
        totalTranslateY = translateY;
        canvas.drawBitmap(bitmap_bg, mMatrix, mPaint);
        canvas.drawBitmap(sourceBitmap, mMatrix, mPaint);
    }

  /**
     *           
     *
     * @param event
     */
    private void move(MotionEvent event) {
        if (event.getPointerCount() == 1) {
            //             ,     
            float xMove = event.getX();
            float yMove = event.getY();
            if (lastXMove == -1 && lastYMove == -1) {
                lastXMove = xMove;
                lastYMove = yMove;
            }
            currentStatus = STATUS_MOVE;
            movedDistanceX = xMove - lastXMove;
            movedDistanceY = yMove - lastYMove;
            //       ,          
            if (totalTranslateX + movedDistanceX > 0) {
                movedDistanceX = 0;
            } else if (width - (totalTranslateX + movedDistanceX) > currentBitmapWidth) {
                movedDistanceX = 0;
            }
            if (totalTranslateY + movedDistanceY > 0) {
                movedDistanceY = 0;
            } else if (height - (totalTranslateY + movedDistanceY) > currentBitmapHeight) {
                movedDistanceY = 0;
            }
            //   onDraw()      
            invalidate();
            lastXMove = xMove;
            lastYMove = yMove;
        } else if (event.getPointerCount() == 2) {
            //              ,     
            centerPointBetweenFingers(event);

            double fingerDis = distanceBetweenFingers(event);
            if (fingerDis > lastFingerDis) {
                currentStatus = STATUS_ZOOM_OUT;
            } else {
                currentStatus = STATUS_ZOOM_IN;
            }
            //         ,          4 ,            
            if ((currentStatus == STATUS_ZOOM_OUT && totalRatio < 4 * initRatio)
                    || (currentStatus == STATUS_ZOOM_IN && totalRatio > initRatio)) {
                scaledRatio = (float) (fingerDis / lastFingerDis);
                totalRatio = totalRatio * scaledRatio;
                if (totalRatio >= 4 * initRatio) {
                    totalRatio = 4 * initRatio;
                } else if (totalRatio < initRatio) {
                    totalRatio = initRatio;
                }
                //   onDraw()      
                invalidate();
                lastFingerDis = fingerDis;
            }
        }
    }

    /**
     *            。
     *
     * @param event
     * @return          
     */
    private double distanceBetweenFingers(MotionEvent event) {
        float disX = Math.abs(event.getX(0) - event.getX(1));
        float disY = Math.abs(event.getY(0) - event.getY(1));
        return Math.sqrt(disX * disX + disY * disY);
    }

    /**
     *               。
     *
     * @param event
     */
    private void centerPointBetweenFingers(MotionEvent event) {
        float xPoint0 = event.getX(0);
        float yPoint0 = event.getY(0);
        float xPoint1 = event.getX(1);
        float yPoint1 = event.getY(1);
        centerPointX = (xPoint0 + xPoint1) / 2;
        centerPointY = (yPoint0 + yPoint1) / 2;
    }

ズームシフトの方法があり、スクリーンの境界検出も実現したので、タッチメソッドを呼び出して、本当にズームシフト機能を実現しなければなりません.
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getActionMasked()){
            case MotionEvent.ACTION_DOWN:
                onTouchDown(event);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                onTouchMove(event);
                if (paintState==paint.PEN){
                    mCanvas.drawPath(mPath,mPaint);
                    currentStatus=0;
                }else if (paintState==paint.ERASER){
                    mCanvas.drawPath(mPath,mEraser);
                    currentStatus=0;
                }else if(paintState==paint.NONE) {
                    move(event);
                }
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                if(paintState==paint.NONE) {
                    //              
                    lastXMove = -1;
                    lastYMove = -1;
                }else{
                    onTouchUp(event);
                    invalidate();
                }

                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                if(paintState==paint.NONE) {
                    if (event.getPointerCount() == 2) {
                        //             ,         
                        lastFingerDis = distanceBetweenFingers(event);
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                if (paintState == paint.NONE) {
                    if (event.getPointerCount() == 2) {
                        //              
                        lastXMove = -1;
                        lastYMove = -1;
                    }
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            default:
                break;
        }
        return true;
    }

   protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (bitmap_fg!=null){
            Log.e(TAG,"ondraw....");
            switch (currentStatus) {
                case STATUS_ZOOM_OUT:

                case STATUS_ZOOM_IN:

                    scale(canvas);
                    break;
                case STATUS_MOVE:
                    translate(canvas);
                    break;
                case STATUS_INIT:

                    initBitmap(canvas);
                default:
                    canvas.drawBitmap(bitmap_bg, mMatrix, mPaint);
                    canvas.drawBitmap(sourceBitmap, mMatrix, mPaint);
                    break;
            }

        }
    }

OKの大功は成し遂げて、何の難点もなくて、私達は主に変数によって前回のスケールを保存して、平行移動の量と、このように私達は平行移動しても尺度変更しても1つの行列で解決することができます.ここまで素晴らしいと思いますが、満足しないでください.次のブログでは、筆画の取り消しと復元、画像保存の機能を実現しますので、引き続き注目してください.ソースダウンロードリンク:グラフィックボード2