Android的图片浏览捏缩放 [英] Android Image View Pinch Zooming

查看:185
本文介绍了Android的图片浏览捏缩放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用code样品从制作多点触摸<意识/一> 缩放图像视图。在ScaleListener我加入 ScaleGestureDetector.getFocusX()和getFocusY()内容放大关于手势的焦点。这是工作的罚款。

的问题是,对第一多触摸整个图片绘画位置改变为当前的触摸点,并从那里放大它。请问你们,请帮我解决这个问题?

下面是我的code样品TouchImageView。

 公共类TouchImageViewSample扩展ImageView的{

民营涂料borderPaint = NULL;
民营涂料backgroundPaint = NULL;

私人浮动mPosX = 0F;
私人浮动mPosY = 0F;

私人浮动mLastTouchX;
私人浮动mLastTouchY;
私有静态最终诠释INVALID_POINTER_ID = -1;
私有静态最后弦乐LOG_TAG =TouchImageView;

//有效指针是一个目前正在朝着我们的目标。
私人诠释mActivePointerId = INVALID_POINTER_ID;

公共TouchImageViewSample(上下文的背景下){
    这(背景下,NULL,0);
}

公共TouchImageViewSample(上下文的背景下,ATTRS的AttributeSet){
    这(背景下,ATTRS,0);
}

私人ScaleGestureDetector mScaleDetector;
私人浮动mScaleFactor = 1.F;

//现有code ...
公共TouchImageViewSample(上下文的背景下,ATTRS的AttributeSet,诠释defStyle){
    超(背景下,ATTRS,defStyle);
    //创建我们的ScaleGestureDetector
    mScaleDetector =新ScaleGestureDetector(上下文,新ScaleListener());

    borderPaint =新的油漆();
    borderPaint.setARGB(255,255,128,0);
    borderPaint.setStyle(Paint.Style.STROKE);
    borderPaint.setStrokeWidth(4);

    backgroundPaint =新的油漆();
    backgroundPaint.setARGB(32,255,255,255);
    backgroundPaint.setStyle(Paint.Style.FILL);

}

@覆盖
公共布尔的onTouchEvent(MotionEvent EV){
    //让ScaleGestureDetector检查所有事件。
    mScaleDetector.onTouchEvent(EV);

    最终诠释行动= ev.getAction();
    开关(行动及放大器; MotionEvent.ACTION_MASK){
    案例MotionEvent.ACTION_DOWN:{
        最终浮动X = ev.getX();
        最终浮动Y = ev.getY();

        mLastTouchX = X;
        mLastTouchY = Y;

        mActivePointerId = ev.getPointerId(0);
        打破;
    }

    案例MotionEvent.ACTION_MOVE:{
        最终诠释pointerIndex = ev.findPointerIndex(mActivePointerId);
        最终浮动X = ev.getX(pointerIndex);
        最终浮动Y = ev.getY(pointerIndex);

        //只有当ScaleGestureDetector没有正在处理手势移动。
        如果(!mScaleDetector.isInProgress()){
            最终浮动DX = X  -  mLastTouchX;
            最终浮动DY = Y  -  mLastTouchY;

            mPosX + = DX;
            mPosY + = DY;

            无效();
        }

        mLastTouchX = X;
        mLastTouchY = Y;
        打破;
    }

    案例MotionEvent.ACTION_UP:{
        mActivePointerId = INVALID_POINTER_ID;
        打破;
    }

    案例MotionEvent.ACTION_CANCEL:{
        mActivePointerId = INVALID_POINTER_ID;
        打破;
    }

    案例MotionEvent.ACTION_POINTER_UP:{
        最终诠释pointerIndex =(ev.getAction()及MotionEvent.ACTION_POINTER_INDEX_MASK)GT;&GT; MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        最终诠释pointerId = ev.getPointerId(pointerIndex);
        如果(pointerId == mActivePointerId){
            //这是我们主动指针往上走。选择一个新的
            //活跃的指针和相应的调整。
            最终诠释newPointerIndex = pointerIndex == 0? 1:0;
            mLastTouchX = ev.getX(newPointerIndex);
            mLastTouchY = ev.getY(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
        }
        打破;
    }
    }

    返回true;
}

/ *
 *(非Javadoc中)
 *
 * @see android.view.View#平局(android.graphics.Canvas)
 * /
@覆盖
公共无效画(油画画布){
    super.draw(画布);
    canvas.drawRect(0,0,的getWidth() -  1,的getHeight() -  1,borderPaint);
}

@覆盖
公共无效的OnDraw(帆布油画){
    canvas.drawRect(0,0,的getWidth() -  1,的getHeight() -  1,backgroundPaint);
    如果(this.getDrawable()!= NULL){
        canvas.save();
        canvas.translate(mPosX,mPosY);

        字模=新的Matrix();
        matrix.postScale(mScaleFactor,mScaleFactor,pivotPointX,
                pivotPointY);
        // canvas.setMatrix(矩阵);

        canvas.drawBitmap(
                ((BitmapDrawable)this.getDrawable())。getBitmap(),矩阵,
                空值);

        // this.getDrawable()画(油画);
        canvas.restore();
    }
}

/ *
 *(非Javadoc中)
 *
 * @看到
 * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable
 *)
 * /
@覆盖
公共无效setImageDrawable(绘制对象绘制){
    //限制为给定的大小,但保持宽高比
    INT宽度= drawable.getIntrinsicWidth();
    INT高= drawable.getIntrinsicHeight();
    mLastTouchX = mPosX = 0;
    mLastTouchY = mPosY = 0;

    INT边框宽度=(INT)borderPaint.getStrokeWidth();
    。mScaleFactor = Math.min(((浮点)getLayoutParams()宽 - 边框宽度)
            /宽度(。(浮点)getLayoutParams()高度 - 边框宽度)
            / 高度);
    pivotPointX =(((浮点)getLayoutParams()宽 - 边框宽度) - (INT)(宽* mScaleFactor))/ 2;
    pivotPointY =(((浮点)getLayoutParams()高度 - 边框宽度) - (INT)(高* mScaleFactor))/ 2;
    super.setImageDrawable(绘制);
}

浮pivotPointX = 0F;
浮pivotPointY = 0F;

私有类ScaleListener扩展
        ScaleGestureDetector.SimpleOnScaleGestureListener {

    @覆盖
    公共布尔onScale(ScaleGestureDetector检测器){
        mScaleFactor * = detector.getScaleFactor();

        pivotPointX = detector.getFocusX();
        pivotPointY = detector.getFocusY();

        Log.d(LOG_TAG,mScaleFactor+ mScaleFactor);
        Log.d(LOG_TAG,pivotPointY+ pivotPointY +,pivotPointX =
                + pivotPointX);
        mScaleFactor = Math.max(0.05f,mScaleFactor);

        无效();
        返回true;
    }
}
 

在这里我如何在我的活动中使用它。

 的ImageView ImageView的=(ImageView的)findViewById(R.id.imgView);

    INT hMargin =(INT)(displayMetrics.widthPixels * 0.10);
    INT vMargin =(INT)(displayMetrics.heightPixels * 0.10);

    RelativeLayout.LayoutParams PARAMS =新RelativeLayout.LayoutParams(displayMetrics.widthPixels  - (hMargin * 2),(INT)(displayMetrics.heightPixels  -  btnCamera.getHeight()) - (vMargin * 2));
    params.leftMargin = hMargin;
    params.topMargin = vMargin;
    imageView.setLayoutParams(PARAMS);
    imageView.setImageDrawable(绘制);
 

在此先感谢。

感谢和问候 阿尼什

解决方案

  @覆盖
公共布尔onTouch(视图V,MotionEvent事件){
    // TODO自动生成方法存根

    ImageView的观点=(ImageView的)V;
    dumpEvent(事件);

    //这里处理触摸事件...
    开关(event.getAction()及MotionEvent.ACTION_MASK){
    案例MotionEvent.ACTION_DOWN:
        savedMatrix.set(矩阵);
        start.set(event.getX(),event.getY());
        Log.d(TAG模式= DRAG);
        模式=阻力;
        打破;
    案例MotionEvent.ACTION_POINTER_DOWN:
        oldDist =间距(事件);
        Log.d(TAG,oldDist =+ oldDist);
        如果(oldDist&GT; 10F){
            savedMatrix.set(矩阵);
            中点(中,事件);
            模式=变焦;
            Log.d(TAG模式= ZOOM);
        }
        打破;
    案例MotionEvent.ACTION_UP:
    案例MotionEvent.ACTION_POINTER_UP:
        模式=无;
        Log.d(TAG模式= NONE);
        打破;
    案例MotionEvent.ACTION_MOVE:
        如果(模式==拖动){
            // ...
            matrix.set(savedMatrix);
            matrix.postTranslate(event.getX() -  start.x,event.getY()
                     -  start.y);
        }否则,如果(模式==变焦){
            浮newDist =间距(事件);
            Log.d(TAG,newDist =+ newDist);
            如果(newDist&GT; 10F){
                matrix.set(savedMatrix);
                浮规模= newDist / oldDist;
                matrix.postScale(规模化,规模化,mid.x,mid.y);
            }
        }
        打破;
    }

    view.setImageMatrix(矩阵);
    返回true;
}

私人无效dumpEvent(MotionEvent事件){
    字符串名称[] = {DOWN,UP,移动,取消,外,
            POINTER_DOWN,POINTER_UP,7?,8?,9? };
    StringBuilder的SB =新的StringBuilder();
    INT行动= event.getAction();
    INT行动code =动作和放大器; MotionEvent.ACTION_MASK;
    sb.append(事件响应_)追加(姓名[动作code])。
    如果(动作code == MotionEvent.ACTION_POINTER_DOWN
            ||行动code == MotionEvent.ACTION_POINTER_UP){
        sb.append((PID).append(
                作用&gt;&GT; MotionEvent.ACTION_POINTER_ID_SHIFT);
        sb.append());
    }
    sb.append([);
    的for(int i = 0; I&LT; event.getPointerCount();我++){
        。sb.append(#)追加(ⅰ);
        sb.append((PID).append(event.getPointerId(ⅰ));
        sb.append()=)追加((int)的event.getX(ⅰ))。
        。sb.append(,)追加((int)的event.getY(ⅰ));
        如果第(i + 1&其中; event.getPointerCount())
            sb.append(;);
    }
    sb.append(]);
    Log.d(TAG,sb.toString());
}

/ **确定第一两个手指之间的空间* /
私人浮动间距(MotionEvent事件){
    浮X = event.getX(0) -  event.getX(1);
    浮Y = event.getY(0) -  event.getY(1);
    返回FloatMath.sqrt(X * X + Y * Y);
}

/ **计算前两个手指的中点* /
私人无效中点(的PointF点,MotionEvent事件){
    浮X = event.getX(0)+ event.getX(1);
    浮Y = event.getY(0)+ event.getY(1);
    point.set(X / 2,Y / 2);
}
 

和不要忘记setscaleType财产的ImageView标签的矩阵一样,

 &LT; ImageView的
            机器人:ID =@ + ID / imageEnhance
            机器人:layout_width =FILL_PARENT
            机器人:layout_height =WRAP_CONTENT
            机器人:layout_gravity =center_horizo​​ntal
            机器人:layout_marginBottom =15dp
            机器人:layout_marginLeft =15dp
            机器人:layout_marginRight =15dp
            机器人:layout_marginTop =15dp
            机器人:背景=@可绘制/ enhanceimageframe
            机器人:scaleType =矩阵&GT;
        &LT; / ImageView的&GT;
 

和使用的变量,

 //这些矩阵将用于移动和放大图像
字模=新的Matrix();
矩阵savedMatrix =新的Matrix();

//我们可以在这3个状态之一
静态最终诠释无= 0;
静态最终诠释DRAG = 1;
静态最终诠释ZOOM = 2;
INT模式=无;

//记住一些东西放大
的PointF开始=新的PointF();
的PointF中期=新的PointF();
浮oldDist = 1F;
字符串savedItemClicked;
 

I am using code sample from Making Sense of Multitouch for zooming image view. On ScaleListener I added ScaleGestureDetector.getFocusX() and getFocusY()for content to zoom about the focal point of the gesture. It is working fine.

The problem is, on first multitouch the entire Image drawing position is changing to the current touch point and zooming it from there. Could you guys please help me to resolve this issue?

Here is My Code Sample For TouchImageView.

public class TouchImageViewSample extends ImageView {

private Paint borderPaint = null;
private Paint backgroundPaint = null;

private float mPosX = 0f;
private float mPosY = 0f;

private float mLastTouchX;
private float mLastTouchY;
private static final int INVALID_POINTER_ID = -1;
private static final String LOG_TAG = "TouchImageView";

// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;

public TouchImageViewSample(Context context) {
    this(context, null, 0);
}

public TouchImageViewSample(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;

// Existing code ...
public TouchImageViewSample(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // Create our ScaleGestureDetector
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());

    borderPaint = new Paint();
    borderPaint.setARGB(255, 255, 128, 0);
    borderPaint.setStyle(Paint.Style.STROKE);
    borderPaint.setStrokeWidth(4);

    backgroundPaint = new Paint();
    backgroundPaint.setARGB(32, 255, 255, 255);
    backgroundPaint.setStyle(Paint.Style.FILL);

}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // Let the ScaleGestureDetector inspect all events.
    mScaleDetector.onTouchEvent(ev);

    final int action = ev.getAction();
    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN: {
        final float x = ev.getX();
        final float y = ev.getY();

        mLastTouchX = x;
        mLastTouchY = y;

        mActivePointerId = ev.getPointerId(0);
        break;
    }

    case MotionEvent.ACTION_MOVE: {
        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
        final float x = ev.getX(pointerIndex);
        final float y = ev.getY(pointerIndex);

        // Only move if the ScaleGestureDetector isn't processing a gesture.
        if (!mScaleDetector.isInProgress()) {
            final float dx = x - mLastTouchX;
            final float dy = y - mLastTouchY;

            mPosX += dx;
            mPosY += dy;

            invalidate();
        }

        mLastTouchX = x;
        mLastTouchY = y;
        break;
    }

    case MotionEvent.ACTION_UP: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
    }

    case MotionEvent.ACTION_CANCEL: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
    }

    case MotionEvent.ACTION_POINTER_UP: {
        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        final int pointerId = ev.getPointerId(pointerIndex);
        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastTouchX = ev.getX(newPointerIndex);
            mLastTouchY = ev.getY(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
        }
        break;
    }
    }

    return true;
}

/*
 * (non-Javadoc)
 * 
 * @see android.view.View#draw(android.graphics.Canvas)
 */
@Override
public void draw(Canvas canvas) {
    super.draw(canvas);
    canvas.drawRect(0, 0, getWidth() - 1, getHeight() - 1, borderPaint);
}

@Override
public void onDraw(Canvas canvas) {
    canvas.drawRect(0, 0, getWidth() - 1, getHeight() - 1, backgroundPaint);
    if (this.getDrawable() != null) {
        canvas.save();
        canvas.translate(mPosX, mPosY);

        Matrix matrix = new Matrix();
        matrix.postScale(mScaleFactor, mScaleFactor, pivotPointX,
                pivotPointY);
        // canvas.setMatrix(matrix);

        canvas.drawBitmap(
                ((BitmapDrawable) this.getDrawable()).getBitmap(), matrix,
                null);

        // this.getDrawable().draw(canvas);
        canvas.restore();
    }
}

/*
 * (non-Javadoc)
 * 
 * @see
 * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable
 * )
 */
@Override
public void setImageDrawable(Drawable drawable) {
    // Constrain to given size but keep aspect ratio
    int width = drawable.getIntrinsicWidth();
    int height = drawable.getIntrinsicHeight();
    mLastTouchX = mPosX = 0;
    mLastTouchY = mPosY = 0;

    int borderWidth = (int) borderPaint.getStrokeWidth();
    mScaleFactor = Math.min(((float) getLayoutParams().width - borderWidth)
            / width, ((float) getLayoutParams().height - borderWidth)
            / height);
    pivotPointX = (((float) getLayoutParams().width - borderWidth) - (int) (width * mScaleFactor)) / 2;
    pivotPointY = (((float) getLayoutParams().height - borderWidth) - (int) (height * mScaleFactor)) / 2;
    super.setImageDrawable(drawable);
}

float pivotPointX = 0f;
float pivotPointY = 0f;

private class ScaleListener extends
        ScaleGestureDetector.SimpleOnScaleGestureListener {

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        mScaleFactor *= detector.getScaleFactor();

        pivotPointX = detector.getFocusX();
        pivotPointY = detector.getFocusY();

        Log.d(LOG_TAG, "mScaleFactor " + mScaleFactor);
        Log.d(LOG_TAG, "pivotPointY " + pivotPointY + ", pivotPointX= "
                + pivotPointX);
        mScaleFactor = Math.max(0.05f, mScaleFactor);

        invalidate();
        return true;
    }
}

And Here how I used it within my activity.

ImageView imageView = (ImageView) findViewById(R.id.imgView);

    int hMargin = (int) (displayMetrics.widthPixels * .10);
    int vMargin = (int) (displayMetrics.heightPixels * .10);

    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(displayMetrics.widthPixels - (hMargin * 2), (int)(displayMetrics.heightPixels - btnCamera.getHeight()) - (vMargin * 2));
    params.leftMargin = hMargin;
    params.topMargin =  vMargin;
    imageView.setLayoutParams(params);
    imageView.setImageDrawable(drawable);

Thanks in advance.

Thanks and Regards Anish

解决方案

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

and dont forget to setscaleType property to matrix of imageview tag like,

<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>

and the variables used are ,

// 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;

这篇关于Android的图片浏览捏缩放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆