【问题标题】:Draw Rectangle Over ImageView for highlight that can be zoom in-out in android在 ImageView 上绘制矩形以突出显示可以在 android 中放大
【发布时间】:2017-07-18 19:51:03
【问题描述】:

我已经从下面的 SO 中引用了这个示例。

1.Draw Line Over ImageView

2.Draw Picture Over ImageView

3.我已经使用这个 ImageView 类让我的图像变成放大图Image Pinch zoom code google

现在我要做的是:

我想通过捏住屏幕来进行放大,其他一点是,当我单击时,应该在图像视图上绘制一个矩形,我还希望这个矩形应该通过 imageView 的放大和缩小来放大和缩小我想通过ScaleImageView 类使用它。

这个输出应该如下图所示。

而且我也知道,这可以通过使用 Relative Layout 来完成,或者可以通过在 android 中使用 SurfaceView 来完成,但我是使用 Surface 视图的新手,我也担心我是否使用另一个视图而不是 imageView 来绘制然后做这两个视图工作放大和缩小。如果我在 ImageView 上使用 SurfaceView,那么 Image 可以放大和缩小。

通过使用此处的捏拉放大示例。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);
    }
}

【问题讨论】:

  • 你想要做什么不是很明显。你能再解释一下吗?
  • @Richard 直到现在我有 ImageView 可以捏放大缩小,现在我有 @Override onDraw 该 ImageView 的方法在用户触摸上绘制矩形,它在 imageview 上绘制一个矩形但是我的问题是 ImageView 能够捏缩放,但矩形不起作用。所以我想应用相同的捏放大缩小该矩形。
  • @Richard 现在我可以认为你得到了我想要做的事情吗?
  • “不行吗”?为什么不对矩形应用相同的变换?
  • 是的。它不工作只有 Image 是放大缩小,因为当我们在 Image 上绘制矩形时,它会在画布上绘制,并且大部分捏缩放都与 Matrix zoom 一起使用。

标签: android imageview zooming


【解决方案1】:

您可能想结帐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..
    ....
}

【讨论】:

  • 我不知道如何将Matrix.mapRect 应用于ImagesView 的画布。很抱歉问这个问题,因为我是使用画布和图像缩放的新手。我正在使用这种方法来绘制canvas.drawRect(rect_x1-30,rect_y1-30, rect_x1+30, rect_y1+30, myPaint);带有单点触控的矩形ImageView
  • 当我使用用于 ImageView 放大的Matrix 时,它仅适用于我的 ImageView 的左上部分,并且它的矩形在我的接触点处绘制不准确。当我使用mCanvasMatrix 时,它不会对矩形进行任何放大。
  • 我看到你更新的答案,但是tempRect 是什么,我的意思是它必须是RectF,但是包含的是什么。
  • 它用于保存mOriginalRect的转换值。昨天我意识到我们不应该修改 mOrignalRect 值。
【解决方案2】:

您可能想扩展 ImageView,在视图 onDraw(Canvas) 中绘制矩形。

将 ImageView 扩展一次以进行捏合缩放(应使用图像视图中的 Matrix 来实现捏合缩放)

再次将其扩展为一个矩形,使用图像矩阵对其进行变换,并在调用 super.draw() 后绘制它。

【讨论】:

  • 我已经使用 ImageView 扩展了类,并且我还在 super.draw() 调用之后应用了 Matrix,但是使矩形放大和缩小并不是完全正确的工作。你可以看到我的 ImageViewScale 是什么我试试。
  • @HaMMedREd 你能解释一下你的答案我真的不明白吗?
  • 你有什么问题。您尝试勾勒的矩形由 4 个点组成。如果将矩形存储为 RectF,并将单位定义为其中的像素(例如 x=10,y=40 处的 30x30 矩形),则将其传递给 getImageMatrix().mapRect(definedRect, translateRect) 然后您将translateRect 并使用 Canvas.drawRect(translatedRect, paint) 绘制它,它应该在给定图像转换矩阵的正确位置绘制它。
  • 我的 src/dest rect 翻译搞砸了,你授予的家长比我解释得更好
【解决方案3】:

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

试试这个!并告诉我。

【讨论】:

  • 你的意思是我必须在我的 ImageView 类的 onDraw 方法中编写这段代码。我用于捏缩放。
  • 您不想在放大和缩小时移动矩形?
  • 是的,一旦用户做出选择,它就应该停留在图像上,就像两个视图一样平坦。
  • 是的,我不想在我们应用放大和缩小时移动。
  • 你可以单点在图像的所有区域绘制矩形吗?
【解决方案4】:

绘制 Ractangle 图像视图

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

【讨论】:

    猜你喜欢
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 1970-01-01
    相关资源
    最近更新 更多