绘制视图缩放图像无法正确缩放:Android

时间:2013-05-16 07:37:09

标签: android canvas imageview zoom

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

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);
    }

}

2 个答案:

答案 0 :(得分:0)

尝试这样的事情,但我不确定

     @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);
}

并且不要忘记将setscaleType属性设置为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;

答案 1 :(得分:0)

带捏缩放和图像上的绘画的图像

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);
}
}