【问题标题】:Paint View Zoom with Image not properly zoom : Android使用图像无法正确缩放的绘制视图缩放:Android
【发布时间】:2013-05-16 07:37:08
【问题描述】:

我使用画布来缩放带有图像的绘制视图,包括使用 setImageMatrix()。如下所示,用于缩放和画线的类。但是出现了问题,那就是整个屏幕变成了放大/缩小,然后当我点击绘画按钮时,我将一个布尔值传递为 false,它在手指触摸时画线。但在画线之后在图像上,我想用这条画线再次开始捏缩放,然后我也可以用画图放大/缩小,但它没有以正确的方式改变画图的 x-y。所以如果有人知道这个问题,请回复。

public class PaintScreen extends Activity {

    Context mContext;
    private Paint mPaint;
    MaskFilter mEmboss;
    MaskFilter mBlur;
    private LinearLayout mPaintBaseLayout;
    private PaintView mPaintView;

    // These matrices will be used to move and zoom image
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new Matrix();
    Matrix savedMatrix2 = new Matrix();

    private int WIDTH = 0;
    private int HEIGHT = 1;

    // We can be in one of these 3 states
    static final int NONE = 0;
    static final int DRAG = 1;
    static final int POINT2 = 2;
    static final int ZOOM = 3;
    int mode = NONE;

    // Remember some things for zooming
    PointF start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;
    float newDist;
    float distanceOffset = 50f;
    float minOffset = 50f;
    float maxOffset = 10000f;
    private boolean falg = true;
    private int startval = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_main);

        this.initialize();

        this.PaintSet();

        Button button = (Button) findViewById(R.id.btnzoom);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (falg) {
                    getFlag(false);
                } else {
                    getFlag(true);
                }
            }
        });

        Button btnset = (Button) findViewById(R.id.btnset);
        btnset.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                startval = 1;
            }
        });
    }

    private void initialize() {
        mPaintBaseLayout = (LinearLayout) findViewById(R.id.paint_paint_base_layout);

        mContext = this;
        mPaint = new Paint();
        mPaintView = new PaintView(mContext);
        mPaintView.setBackgroundColor(Color.TRANSPARENT);
        mPaintBaseLayout.addView(mPaintView, new LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        mPaintBaseLayout.setBackgroundColor(Color.TRANSPARENT);

        mPaintView.setScaleType(ScaleType.MATRIX);
        mPaintView.setMPaint(mPaint);
        Bitmap bm = BitmapFactory
                .decodeResource(getResources(), R.drawable.nat);

        mPaintView.setImageBitmap(bm);

        mPaintView.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                PaintView view = (PaintView) v;

                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    if (falg) {
                        savedMatrix.set(matrix);
                        start.set(event.getX(), event.getY());
                        mode = DRAG;
                    } else {
                        view.onTouchEvent(event);
                    }
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    if (falg) {
                        oldDist = spacing(event);
                        if (oldDist > 10f) {
                            start.set(event.getX(), event.getY());
                            savedMatrix.set(matrix);
                            midPoint(mid, event);
//                           mode = POINT2;
                            mode = ZOOM;
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (falg) {
                        mode = NONE;
                        distanceOffset = minOffset;
                    }
                case MotionEvent.ACTION_POINTER_UP:
                    if (falg) {
                        mode = NONE;
                        distanceOffset = minOffset;
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (falg) {
                        if (mode == POINT2) {
                            newDist = spacing(event);
                            if (newDist - oldDist > 5f
                                    || newDist - oldDist < -5f) {
                                mode = ZOOM;
                            } else {
                                start.set(event.getX(), event.getY());
                                mode = DRAG;

                            }
                        } else if (mode == DRAG) {
                            matrix.set(savedMatrix);
                            matrix.postTranslate(event.getX() - start.x,
                                    event.getY() - start.y);

                        } else if (mode == ZOOM) {
                            newDist = spacing(event);
                            if (newDist > 10f) {
                                matrix.set(savedMatrix);
                                float scale = newDist / oldDist;
                                matrix.postScale(scale, scale, mid.x, mid.y);
                            }
                        }
                    } else {
                        view.onTouchEvent(event);
                    }
                    break;
                }

//              if (startval == 1) {
                    view.cMatrix(matrix);
//              }
                view.setImageMatrix(matrix);
                matrixTurning(matrix, view);
                return true;
            }
        });
    }

    public boolean getFlag(boolean b) {
        return falg = b;
    }

    /** Determine the space between the first two fingers */
    private static float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    private static void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }

    private void matrixTurning(Matrix matrix, ImageView view) {

        float[] value = new float[9];
        matrix.getValues(value);
        float[] savedValue = new float[9];
        savedMatrix2.getValues(savedValue);

        // view size
        int width = view.getWidth();
        int height = view.getHeight();

        // image size
        Drawable d = view.getDrawable();
        if (d == null)
            return;
        int imageWidth = d.getIntrinsicWidth();
        int imageHeight = d.getIntrinsicHeight();
        int scaleWidth = (int) (imageWidth * value[0]);
        int scaleHeight = (int) (imageHeight * value[0]);

        if (value[2] < width - scaleWidth)
            value[2] = width - scaleWidth;
        if (value[5] < height - scaleHeight)
            value[5] = height - scaleHeight;
        if (value[2] > 0)
            value[2] = 0;
        if (value[5] > 0)
            value[5] = 0;

        if (value[0] > 10 || value[4] > 10) {
            value[0] = savedValue[0];
            value[4] = savedValue[4];
            value[2] = savedValue[2];
            value[5] = savedValue[5];
        }

        if (imageWidth > width || imageHeight > height) {

            if (scaleWidth < width && scaleHeight < height) {
                int target = WIDTH;

                if (imageWidth < imageHeight)
                    target = HEIGHT;

                if (target == WIDTH)
                    value[0] = value[4] = (float) width / imageWidth;
                if (target == HEIGHT)
                    value[0] = value[4] = (float) height / imageHeight;

                scaleWidth = (int) (imageWidth * value[0]);
                scaleHeight = (int) (imageHeight * value[4]);

                if (scaleWidth == width)
                    value[0] = value[4] = (float) width / imageWidth;
                if (scaleHeight == height)
                    value[0] = value[4] = (float) height / imageHeight;
            }

        } else {
            if (value[0] < 1)
                value[0] = 1;
            if (value[4] < 1)
                value[4] = 1;
        }

        scaleWidth = (int) (imageWidth * value[0]);
        scaleHeight = (int) (imageHeight * value[4]);

        if (scaleWidth < width) {
            value[2] = (float) width / 2 - (float) scaleWidth / 2;
        }
        if (scaleHeight < height) {
            value[5] = (float) height / 2 - (float) scaleHeight / 2;
        }

        matrix.setValues(value);
        savedMatrix2.set(matrix);

    }

    public void PaintSet() {

        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(0xFFFF0000);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(10);

        // getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);
        mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
        mBlur = new BlurMaskFilter(24, BlurMaskFilter.Blur.NORMAL);
    }

    public void colorChanged(int color) {
        mPaint.setColor(color);
    }
}

class PaintView extends ImageView {

    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint mBitmapPaint;

    // onDraw
    private Paint mPaint;

    // onTouch
    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    public PaintView(Context context) {
        this(context, null);
    }

    public PaintView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mBitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888);
        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // canvas.drawColor(0xFFAAAAAA);
        super.onDraw(canvas);
        mCanvas = canvas;
        // canvas = mCanvas;
        Matrix localMatrix = new Matrix();
        localMatrix.setRectToRect(
                new RectF(0.0F, 0.0F, mBitmap.getWidth(), mBitmap
                        .getHeight()),
                new RectF(0.0F, 0.0F, this.mCanvas.getWidth(),
                        this.mCanvas.getHeight()),
                Matrix.ScaleToFit.CENTER);
        canvas.drawBitmap(mBitmap, localMatrix, mBitmapPaint);
//      canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
//      canvas.drawBitmap(mBitmap, PaintScreen.matrix, mBitmapPaint);
        canvas.drawPath(mPath, mPaint);

    }

    public void setMPaint(Paint paint) {
        mPaint = paint;
    }

    private void touchStart(float x, float y) {
        // mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }

    private void touchMove(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            mX = x;
            mY = y;
        }
    }

    private void touchUp() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        Log.d("PaintView", "ev ->" + event.getAction());

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touchStart(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touchMove(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            touchUp();
            invalidate();
            break;
        }
        return true;
    }

    public void cMatrix(Matrix matrix) {
        mCanvas.setMatrix(matrix);
    }

}

【问题讨论】:

    标签: android canvas imageview zooming


    【解决方案1】:

    试试这样的,但我不确定

         @Override
      public boolean onTouch(View v, MotionEvent event) {
    // TODO Auto-generated method stub
    ImageView view = (ImageView) v;
    dumpEvent(event);
    // Handle touch events here...
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
        savedMatrix.set(matrix);
        start.set(event.getX(), event.getY());
        Log.d(TAG, "mode=DRAG");
        mode = DRAG;
        break;
    case MotionEvent.ACTION_POINTER_DOWN:
        oldDist = spacing(event);
        Log.d(TAG, "oldDist=" + oldDist);
        if (oldDist > 10f) {
            savedMatrix.set(matrix);
            midPoint(mid, event);
            mode = ZOOM;
            Log.d(TAG, "mode=ZOOM");
        }
        break;
    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_POINTER_UP:
        mode = NONE;
        Log.d(TAG, "mode=NONE");
        break;
    case MotionEvent.ACTION_MOVE:
        if (mode == DRAG) {
            // ...
            matrix.set(savedMatrix);
            matrix.postTranslate(event.getX() - start.x, event.getY()
                    - start.y);
        } else if (mode == ZOOM) {
            float newDist = spacing(event);
            Log.d(TAG, "newDist=" + newDist);
            if (newDist > 10f) {
                matrix.set(savedMatrix);
                float scale = newDist / oldDist;
                matrix.postScale(scale, scale, mid.x, mid.y);
            }
        }
        break;
    }
    view.setImageMatrix(matrix);
    return true;
    }
     private void dumpEvent(MotionEvent event) {
    String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
            "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
    StringBuilder sb = new StringBuilder();
    int action = event.getAction();
    int actionCode = action & MotionEvent.ACTION_MASK;
    sb.append("event ACTION_").append(names[actionCode]);
    if (actionCode == MotionEvent.ACTION_POINTER_DOWN
            || actionCode == MotionEvent.ACTION_POINTER_UP) {
        sb.append("(pid ").append(
                action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
        sb.append(")");
    }
    sb.append("[");
    for (int i = 0; i < event.getPointerCount(); i++) {
        sb.append("#").append(i);
        sb.append("(pid ").append(event.getPointerId(i));
        sb.append(")=").append((int) event.getX(i));
        sb.append(",").append((int) event.getY(i));
        if (i + 1 < event.getPointerCount())
            sb.append(";");
    }
    sb.append("]");
    Log.d(TAG, sb.toString());
    }
     /** Determine the space between the first two fingers */
      private float spacing(MotionEvent event) {
     float x = event.getX(0) - event.getX(1);
     float y = event.getY(0) - event.getY(1);
     return FloatMath.sqrt(x * x + y * y);
     }
    /** Calculate the mid point of the first two fingers */
      private void midPoint(PointF point, MotionEvent event) {
    float x = event.getX(0) + event.getX(1);
    float y = event.getY(0) + event.getY(1);
    point.set(x / 2, y / 2);
    }
    

    并且不要忘记将scaleType属性设置为imageview标签的矩阵,例如,

           <ImageView
            android:id="@+id/imageEnhance"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="15dp"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:layout_marginTop="15dp"
            android:background="@drawable/enhanceimageframe"
            android:scaleType="matrix" >
        </ImageView>
    

    并且使用的变量是,

         // These matrices will be used to move and zoom image
       Matrix matrix = new Matrix();
        Matrix savedMatrix = new Matrix();
          // We can be in one of these 3 states
        static final int NONE = 0;
        static final int DRAG = 1;
        static final int ZOOM = 2;
        int mode = NONE;
          // Remember some things for zooming
        PointF start = new PointF();
        PointF mid = new PointF();
        float oldDist = 1f;
        String savedItemClicked;
    

    【讨论】:

    • 你想在你的视图中绘画
    【解决方案2】:

    图像缩放并在图像上绘画

    imageView.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    ImageView view = (ImageView) v;
    
                    switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        savedMatrix.set(matrix1);
                        start.set(event.getX(), event.getY());
                        mode = DRAG;
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        oldDist = spacing(event);
                        if (oldDist > 10f) {
                            start.set(event.getX(), event.getY());
                            savedMatrix.set(matrix1);
                            midPoint(mid, event);
                            // mode = POINT2;
                            mode = ZOOM;
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        mode = NONE;
                        distanceOffset = minOffset;
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        distanceOffset = minOffset;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (mode == POINT2) {
                            newDist = spacing(event);
                            if (newDist - oldDist > 5f
                                    || newDist - oldDist < -5f) {
                                mode = ZOOM;
                            } else {
                                start.set(event.getX(), event.getY());
                                mode = DRAG;
                            }
                        } else if (mode == DRAG) {
                            matrix1.set(savedMatrix);
                            matrix1.postTranslate(event.getX() - start.x,
                                    event.getY() - start.y);
                        } else if (mode == ZOOM) {
                            newDist = spacing(event);
                            if (newDist > 10f) {
                                matrix1.set(savedMatrix);
                                float scale = newDist / oldDist;
                                matrix1.postScale(scale, scale, mid.x,
                                        mid.y);
                                finalscale = scale;
                            }
                        }
                        break;
                    }
    
                    view.setImageMatrix(matrix1);
    //              matrixTurning(matrix1, view);
                    return true; // indicate event was handled
                }
            });
        }
    
    
    
    mPaintView.setOnTouchListener(new OnTouchListener() {
    
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    PaintView view = (PaintView) v;
                    view.setScaleType(ImageView.ScaleType.MATRIX);
                    switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        if (falg) {
                            savedMatrix.set(matrix);
                            start.set(event.getX(), event.getY());
                            mode = DRAG;
                        } else {
                            view.onTouchEvent(event);
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        if (falg) {
                            oldDist = spacing(event);
                            if (oldDist > 10f) {
                                start.set(event.getX(), event.getY());
                                savedMatrix.set(matrix);
                                midPoint(mid, event);
                                mode = ZOOM;
                            }
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (falg) {
                            mode = NONE;
                            distanceOffset = minOffset;
                        }
                    case MotionEvent.ACTION_POINTER_UP:
                        if (falg) {
                            mode = NONE;
                            distanceOffset = minOffset;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (falg) {
                            if (mode == POINT2) {
                                newDist = spacing(event);
                                if (newDist - oldDist > 5f
                                        || newDist - oldDist < -5f) {
                                    mode = ZOOM;
                                } else {
                                    start.set(event.getX(), event.getY());
                                    mode = DRAG;
                                }
                            } else if (mode == DRAG) {
                                matrix.set(savedMatrix);
                                matrix.postTranslate(event.getX() - start.x,
                                        event.getY() - start.y);
                            } else if (mode == ZOOM) {
                                newDist = spacing(event);
                                if (newDist > 10f) {
                                    matrix.set(savedMatrix);
                                    float scale = newDist / oldDist;
                                    matrix.postScale(scale, scale, mid.x, mid.y);
                                    finalscale = scale;
                                }
                            }
                        } else {
                            view.onTouchEvent(event);
                        }
                        break;
                    }
    
                    limitZoom(matrix);
                    view.setImageMatrix(matrix);
    
                    matrixTurning(matrix, view);
                    RectF r = new RectF();
                    matrix.mapRect(r);
                    scaledImageOffsetX = r.left;
                    scaledImageOffsetY = r.top;
    
                    return true;
                }
            });
        }
    
    
        private void limitZoom(Matrix m) {
    
            float[] values = new float[9];
            m.getValues(values);
            float scaleX = values[Matrix.MSCALE_X];
            float scaleY = values[Matrix.MSCALE_Y];
            if(scaleX > MAX_ZOOM) {
                scaleX = MAX_ZOOM;
            } else if(scaleX < MIN_ZOOM) {
                scaleX = MIN_ZOOM;
            }
    
            if(scaleY > MAX_ZOOM) {
                scaleY = MAX_ZOOM;
            } else if(scaleY < MIN_ZOOM) {
                scaleY = MIN_ZOOM;
            }
    
            values[Matrix.MSCALE_X] = scaleX;
            values[Matrix.MSCALE_Y] = scaleY; 
            m.setValues(values);
        }
    
        public boolean getFlag(boolean b) {
            return falg = b;
        }
    

    PaintView.class

        class PaintView extends ImageView {
    
    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint mBitmapPaint;
    
    // onDraw
    private Paint mPaint;
    
    // onTouch
    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;
    
    public PaintView(Context context) {
        this(context, null);
    }
    
    public PaintView(Context context, AttributeSet attrs) {
        super(context, attrs);
    
        mBitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888);
        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    
    }
    
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        // canvas.drawColor(0xFFAAAAAA);
        super.onDraw(canvas);
        mCanvas = canvas;
        // canvas = mCanvas;
         canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        // canvas.drawBitmap(mBitmap, PaintScreen.matrix, mBitmapPaint);
        canvas.drawPath(mPath, mPaint);
    
    }
    
    public void clear() {
        mPaint.reset();
        // invalidate();
    }
    
    public void setMPaint(Paint paint) {
        mPaint = paint;
    }
    
    private void touchStart(float x, float y) {
        // mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }
    
    private void touchMove(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            mX = x;
            mY = y;
        }
    }
    
    private void touchUp() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
    
        Log.d("PaintView", "ev ->" + event.getAction());
    
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touchStart(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touchMove(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            touchUp();
            invalidate();
            break;
        }
        return true;
    }
    
    public void cMatrix(Matrix matrix) {
        mCanvas.setMatrix(matrix);
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-12
      • 1970-01-01
      • 2016-10-07
      • 1970-01-01
      • 2021-09-10
      相关资源
      最近更新 更多