我从下面这个例子中引用了这个例子。
3.我已使用此ImageView类为我的图像放大Image Pinch zoom code google。
现在我要做的是:
我想通过捏住屏幕进行放大,其他点是当我单击时,应该在图像视图上绘制一个矩形,我也希望这个矩形应该放大&使用imageView的放大和缩小,我希望通过ScaleImageView
类使用它。
此输出应如下图所示。
我也知道,这可以通过使用Relative Layout
来完成,也可以在android中使用SurfaceView
但我是新用的Surface视图,我也担心如果我使用另一个视图在imageView上绘制然后执行此操作两个视图工作放大和缩小。如果我在ImageView上使用SurfaceView,那么可以放大和缩小图像。
通过此处使用此缩放放大示例。example that i use pinch zoom。
现在我通过下面的代码在单个触摸上绘制矩形。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.v("Log_tag", "Draw Image View");
//Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.rect_image);
//canvas.drawColor(Color.BLACK);
//canvas.drawBitmap(_scratch, 10, 10, null);
Drawable d = getDrawable();
//Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565);
/*if(bitmap!=null){
if (x1 > 0 || x2 > 0 || y1 > 0 || y2 > 0){
Log.v("Log_tag", "ImageBitmap is draw");
//Canvas mCanvas=new Canvas(bitmap);
//mCanvas.drawRect(x1, y1, x2, y2, mPaint);
// canvas.clipRect(left, top, right, bottom);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(1);
paint.setColor(0xFF000000
+ ((int)(PRESET_PRESSURE * pressure) <<16)
+ ((int)(PRESET_PRESSURE * pressure) << 8)
+ (int)(PRESET_PRESSURE * pressure));
//mCanvas.drawCircle(x1, y1, (PRESET_SIZE * size), paint);
}
}*/
//canvas.save();
//canvas.translate(mPosX, mPosY);
// canvas.scale(mScaleFactor, mScaleFactor);
mBitmapDrawable.draw(canvas);
Paint myPaint = new Paint();
myPaint.setColor(Color.GREEN);
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(1);
Log.v("Log_tag", "Redraw with this point");
canvas.drawRect(rect_x1-30,rect_y1-30, rect_x1+30, rect_y1+30, myPaint);
mCanvasMatrix=canvas.getMatrix();
mImageCanvas=canvas;
canvas.setMatrix(mCanvasMatrix);
//canvas.restore();
}
更新
以下是用于ImageView捏缩放的类。
public class ImageViewScale extends ImageView implements OnTouchListener {
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//canvas.save();
//canvas.scale(mScale, mScale);
mCanvasMatrix=canvas.getMatrix();
Paint myPaint = new Paint();
myPaint.setColor(Color.GREEN);
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(1);
if(mCanvasMatrix!=null){
if(orignalRect!=null)
mCanvasMatrix.mapRect(orignalRect);
}
if(orignalRect!=null){
canvas.drawRect(orignalRect,myPaint);
}
//canvas.drawRect(rect_x1-30,rect_y1-30, rect_x1+30, rect_y1+30, myPaint);
int canavs_width=canvas.getWidth();
int canavs_height=canvas.getHeight();
canvas.setMatrix(mCanvasMatrix);
//canvas.setMatrix(mMatrix);
if(mDrawable!=null){
//mDrawable.draw(canvas);
Log.v("Log_tag", "draw with Canvas is done W:"+ canavs_width+"H:"+ canavs_height);
}
//canvas.restore();
}
private float MAX_SCALE = 2f;
private int DOUBLE_TAP_SECOND = 400;
private float CANVAS_MAX_SCALE=2f;
float rect_x1=50;
float rect_y1=150;
private Matrix mMatrix;
private Matrix mCanvasMatrix;
private final float[] mCanvasMatrixValues=new float[9];
private final float[] mMatrixValues = new float[9];
RectF orignalRect;
private Drawable mDrawable;
private ImageView mImageView;
// display width height.
private int mWidth;
private int mHeight;
private int mIntrinsicWidth;
private int mIntrinsicHeight;
private int mCanvasWidth;
private int mCanvasHeight;
private float mScale;
private float mMinScale;
private float mCanvasMinScale;
// double tap for determining
private long mLastTime = 0;
private boolean isDoubleTap;
private int mDoubleTapX;
private int mDoubleTapY;
private float mPrevDistance;
private boolean isScaling;
private int mPrevMoveX;
private int mPrevMoveY;
String TAG = "ScaleImageView";
public ImageViewScale(Context context, AttributeSet attr) {
super(context, attr);
initialize();
}
public ImageViewScale(Context context) {
super(context);
initialize();
}
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
this.initialize();
}
private void initialize() {
this.setScaleType(ScaleType.MATRIX);
this.mMatrix = new Matrix();
Drawable d = getDrawable();
mDrawable=d;
if (d != null) {
mIntrinsicWidth = d.getIntrinsicWidth();
mIntrinsicHeight = d.getIntrinsicHeight();
setOnTouchListener(this);
}
}
@Override
protected boolean setFrame(int l, int t, int r, int b) {
Log.v("Log_tag", "Size are here "+ l + t + r+ b);
mWidth = r - l;
mHeight = b - t;
mMatrix.reset();
mScale = (float) r / (float) mIntrinsicWidth;
int paddingHeight = 0;
int paddingWidth = 0;
// scaling vertical
if (mScale * mIntrinsicHeight > mHeight) {
mScale = (float) mHeight / (float) mIntrinsicHeight;
mMatrix.postScale(mScale, mScale);
paddingWidth = (r - mWidth) / 2;
paddingHeight = 0;
// scaling horizontal
} else {
mMatrix.postScale(mScale, mScale);
paddingHeight = (b - mHeight) / 2;
paddingWidth = 0;
}
mMatrix.postTranslate(paddingWidth, paddingHeight);
setImageMatrix(mMatrix);
mMinScale = mScale;
zoomTo(mScale, mWidth / 2, mHeight / 2);
cutting();
return super.setFrame(l, t, r, b);
}
protected float getValue(Matrix matrix, int whichValue) {
matrix.getValues(mMatrixValues);
return mMatrixValues[whichValue];
}
//New Added
protected float getCanvasValue(Matrix matrix,int whichvalues){
mCanvasMatrix.getValues(mCanvasMatrixValues);
return mCanvasMatrixValues[whichvalues];
}
protected float getScale() {
return getValue(mMatrix, Matrix.MSCALE_X);
}
//New added Method
protected float getCanvasScale(){
return getCanvasValue(mCanvasMatrix, Matrix.MSCALE_X);
}
protected float getTranslateX() {
return getValue(mMatrix, Matrix.MTRANS_X);
}
//New added Method
protected float getCanvasTranslateX(){
return getCanvasValue(mCanvasMatrix, Matrix.MTRANS_X);
}
protected float getTranslateY() {
return getValue(mMatrix, Matrix.MTRANS_Y);
}
//New Added Method
protected float getCanvasTranslateY(){
return getCanvasValue(mCanvasMatrix, Matrix.MTRANS_Y);
}
protected void maxZoomTo(int x, int y) {
if (mMinScale != getScale() && (getScale() - mMinScale) > 0.1f) {
// threshold 0.1f
float scale = mMinScale / getScale();
zoomTo(scale, x, y);
} else {
float scale = MAX_SCALE / getScale();
zoomTo(scale, x, y);
}
}
protected void zoomTo(float scale, int x, int y) {
if (getScale() * scale < mMinScale) {
return;
}
if (scale >= 1 && getScale() * scale > MAX_SCALE) {
return;
}
mMatrix.postScale(scale, scale);
// move to center
mMatrix.postTranslate(-(mWidth * scale - mWidth) / 2,
-(mHeight * scale - mHeight) / 2);
// move x and y distance
mMatrix.postTranslate(-(x - (mWidth / 2)) * scale, 0);
mMatrix.postTranslate(0, -(y - (mHeight / 2)) * scale);
setImageMatrix(mMatrix);
}
protected void zoomToCanvas(float scale,int x,int y){
if(getCanvasScale()* scale<mCanvasMinScale){
return;
}
if(scale>=1 && getCanvasScale()*scale> CANVAS_MAX_SCALE){
return;
}
mCanvasMatrix.postScale(scale, scale);
}
public void cutting() {
int width = (int) (mIntrinsicWidth * getScale());
int height = (int) (mIntrinsicHeight * getScale());
if (getTranslateX() < -(width - mWidth)) {
mMatrix.postTranslate(-(getTranslateX() + width - mWidth), 0);
}
if (getTranslateX() > 0) {
mMatrix.postTranslate(-getTranslateX(), 0);
}
if (getTranslateY() < -(height - mHeight)) {
mMatrix.postTranslate(0, -(getTranslateY() + height - mHeight));
}
if (getTranslateY() > 0) {
mMatrix.postTranslate(0, -getTranslateY());
}
if (width < mWidth) {
mMatrix.postTranslate((mWidth - width) / 2, 0);
}
if (height < mHeight) {
mMatrix.postTranslate(0, (mHeight - height) / 2);
}
setImageMatrix(mMatrix);
}
private float distance(float x0, float x1, float y0, float y1) {
float x = x0 - x1;
float y = y0 - y1;
return FloatMath.sqrt(x * x + y * y);
}
private float dispDistance() {
return FloatMath.sqrt(mWidth * mWidth + mHeight * mHeight);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int touchCount = event.getPointerCount();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
case MotionEvent.ACTION_POINTER_2_DOWN:
if (touchCount >= 2) {
float distance = distance(event.getX(0), event.getX(1),
event.getY(0), event.getY(1));
mPrevDistance = distance;
isScaling = true;
} else {
if (System.currentTimeMillis() <= mLastTime + DOUBLE_TAP_SECOND) {
if (30 > Math.abs(mPrevMoveX - event.getX())
+ Math.abs(mPrevMoveY - event.getY())) {
isDoubleTap = true;
mDoubleTapX = (int) event.getX();
mDoubleTapY = (int) event.getY();
}
}
mLastTime = System.currentTimeMillis();
mPrevMoveX = (int) event.getX();
mPrevMoveY = (int) event.getY();
}
break;
case MotionEvent.ACTION_MOVE:
if (touchCount >= 2 && isScaling) {
float dist = distance(event.getX(0), event.getX(1),
event.getY(0), event.getY(1));
float scale = (dist - mPrevDistance) / dispDistance();
mPrevDistance = dist;
scale += 1;
scale = scale * scale;
zoomTo(scale, mWidth / 2, mHeight / 2);
cutting();
} else if (!isScaling) {
int distanceX = mPrevMoveX - (int) event.getX();
int distanceY = mPrevMoveY - (int) event.getY();
mPrevMoveX = (int) event.getX();
mPrevMoveY = (int) event.getY();
mMatrix.postTranslate(-distanceX, -distanceY);
cutting();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_2_UP:
if (event.getPointerCount() <= 1) {
isScaling = false;
if (isDoubleTap) {
if (30 > Math.abs(mDoubleTapX - event.getX())
+ Math.abs(mDoubleTapY - event.getY())) {
maxZoomTo(mDoubleTapX, mDoubleTapY);
cutting();
}
}
}
isDoubleTap = false;
break;
}
return true;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int count_touch=event.getPointerCount();
switch(event.getAction()){
case MotionEvent.ACTION_UP:
float point_x=event.getX();
float point_y=event.getY();
rect_x1=point_x;
rect_y1=point_y;
if(count_touch==1){
orignalRect=new RectF(rect_x1-30, rect_y1-30, rect_x1+30, rect_y1+30);
invalidate();
}
break;
}
return super.onTouchEvent(event);
}
}
答案 0 :(得分:4)
您可能想要结帐Matrix.mapRect。使用此方法将矩形转换为与imageview中的图像相同的量。
boolean onTouch(MotionEvent ev) {
....
// this rect dimensions should be initial values and should be a member.
mOriginalRect = new RectF(rect_x1-30, rect_y1-30, rect_x1+30, rect_y1+30);
.....
}
@Override
protected void onDraw(Canvas canvas) {
....
mCanvasMatrix = canvas.getMatrix(); ///matrix should have scale values..
mCanvasMatrix.mapRect(tempRect, mOriginalRect); // mOriginalRect is src
canvas.drawRect(tempRect, myPaint); // draw tempRect..
....
}
答案 1 :(得分:1)
您可能想要在视图onDraw(Canvas)中扩展ImageView,您将绘制矩形。
扩展ImageView一次以进行双指缩放(应使用图像视图中的矩阵来实现捏缩放)
再次扩展它以获取一个矩形,使用图像矩阵对其进行转换,并在super.draw()调用后绘制它。
答案 2 :(得分:1)
@ Herry - 我在这类问题上做了一个小POC,发现在改变imageview时我们必须完全转换画布。
示例:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Resources res = this.getResources();
Bitmap mBitmap = BitmapFactory.decodeResource(res, R.drawable.circlered);
canvas.save();
canvas.translate(1f, 1f);
canvas.restore();
canvas.save();
canvas.concat(mMatrix);
canvas.drawBitmap(mBitmap, 100, 150, null);
}
试试这个!让我知道。
答案 3 :(得分:0)
public class RactangleImageView extends ImageView {
private static final int strockwidth = 6;
private Paint paintBorder;
private Bitmap bitmap;
private int strokeWidthPx;
private RectF rectF;
private RadialGradient radialGradient;
public RactangleImageView(Context context) {
super(context);
init();
}
private void init() {
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.imageicon);
strokeWidthPx = (int) (strockwidth * getResources().getDisplayMetrics().density);
int halfStrokeWidthPx = strokeWidthPx / 2;
paintBorder = new Paint();
paintBorder.setStyle(Paint.Style.FILL);
int totalWidth = bitmap.getWidth() + strokeWidthPx * 2;
int totalHeight = bitmap.getHeight() + strokeWidthPx * 2;
radialGradient = new RadialGradient(totalWidth /2, totalHeight /2, totalWidth /2, new int[] {Color.BLACK, Color.GREEN}, null, Shader.TileMode.MIRROR);
paintBorder.setShader(radialGradient);
setImageBitmap(Bitmap.createBitmap(totalWidth, totalHeight, Bitmap.Config.ARGB_8888));
rectF = new RectF(halfStrokeWidthPx, halfStrokeWidthPx, totalWidth - halfStrokeWidthPx, totalHeight - halfStrokeWidthPx);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRoundRect(rectF, 40, 40, paintBorder);
canvas.drawBitmap(bitmap,strokeWidthPx, strokeWidthPx, null);
}
}