在ImageView上绘制矩形以突出显示可在Android中放大的内容

时间:2012-05-07 12:38:58

标签: android imageview zoom

我从下面这个例子中引用了这个例子。

1。Draw Line Over ImageView

2。Draw Picture Over ImageView

3.我已使用此ImageView类为我的图像放大Image Pinch zoom code google

现在我要做的是:

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

此输出应如下图所示。

you can see when i make single tap over ImageViewit will draw rectangle like showing in image

我也知道,这可以通过使用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);
    }
}

4 个答案:

答案 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)

绘制Ractangle imageview

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