使用图像无法正确缩放的绘制视图缩放:Android
Posted
技术标签:
【中文标题】使用图像无法正确缩放的绘制视图缩放:Android【英文标题】:Paint View Zoom with Image not properly zoom : 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);
【问题讨论】:
【参考方案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_ android:layout_ 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);
【讨论】:
以上是关于使用图像无法正确缩放的绘制视图缩放:Android的主要内容,如果未能解决你的问题,请参考以下文章
添加背景图像时,Xamarin android网格无法正确缩放单元格
Android在画布上操纵图像 - 使用触摸,移动,放大/缩小,缩放