使用ImageView子类时,捏缩放的性能非常慢

时间:2014-10-07 05:59:09

标签: java android imageview pinchzoom

我使用以下代码添加捏缩放和平移

public class Touch extends Activity implements OnTouchListener {
private static final String TAG = "Touch";

private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 5.0f;

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

ImageView image2;
image2 = (ImageView)this.findViewById(R.id.imageView2);
image2.setOnTouchListener(new OnTouchListener() {

                public boolean onTouch(View v, MotionEvent event) {

                     ImageView view = (ImageView) image2;
                      // Handle touch events here...
                        switch (event.getAction() & MotionEvent.ACTION_MASK) {
                        case MotionEvent.ACTION_DOWN:
                            savedMatrix.set(matrix);
                            start.set(event.getX(), event.getY());
                            mode = DRAG;
                            break;
                        case MotionEvent.ACTION_POINTER_DOWN:
                            oldDist = spacing(event);
                            if (oldDist > 10f) {
                                savedMatrix.set(matrix);
                                midPoint(mid, event);
                                mode = ZOOM;
                            }
                            break;
                        case MotionEvent.ACTION_UP:
                        case MotionEvent.ACTION_POINTER_UP:
                            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);
                                if (newDist > 10f) {
                                    matrix.set(savedMatrix);
                                    float scale = newDist / oldDist;
                                    matrix.postScale(scale, scale, mid.x, mid.y);
                                }
                            }
                            break;
                        }
                        view.setImageMatrix(matrix);
}

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

使用800kb的图像进行测试时,这很顺利。

我想做一些绘图并获得onDraw方法,我将此代码移动到MyImageView - 从ImageView继承,通过xml将此自定义项添加到布局。它加载但性能非常慢。我也尝试过其他代码,但是当在子类中创建时,性能非常慢。有人可以告诉我:

  1. 我应该怎样做才能使子类同样顺利运作?

  2. 我是否可以从Activity访问ImageView的onDraw方法而无需使用自定义类?我在说这个:

    image2 =(ImageView)this.findViewById(R.id.imageView2);

1 个答案:

答案 0 :(得分:0)

创建自定义ImageView并将该自定义imageview应用于xml。这将适用于平滑缩放和缩小。

   import android.content.Context;
   import android.graphics.Matrix;
   import android.graphics.PointF;
   import android.graphics.drawable.Drawable;
   import android.util.AttributeSet;
   import android.util.Log;
   import android.view.MotionEvent;
   import android.view.ScaleGestureDetector;
   import android.view.View;
   import android.widget.ImageView;

   public class TouchImageView extends ImageView {

   Matrix 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 last = new PointF();
   PointF start = new PointF();
   float minScale = 1f;
   float maxScale = 3f;
   float[] m;


   int viewWidth, viewHeight;
   static final int CLICK = 3;
   float saveScale = 1f;
   protected float origWidth, origHeight;
   int oldMeasuredWidth, oldMeasuredHeight;


   ScaleGestureDetector mScaleDetector;

   Context context;

   public TouchImageView(Context context) {
   super(context);
   sharedConstructing(context);
    }

  public TouchImageView(Context context, AttributeSet attrs) {
 super(context, attrs);
sharedConstructing(context);
 }
 public float getSaveScale() {
 return saveScale;
 }

private void sharedConstructing(Context context) {
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix = new Matrix();
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);

setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        mScaleDetector.onTouchEvent(event);
        PointF curr = new PointF(event.getX(), event.getY());

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                last.set(curr);
                start.set(last);
                mode = DRAG;
                break;

            case MotionEvent.ACTION_MOVE:
                if (mode == DRAG) {
                    float deltaX = curr.x - last.x;
                    float deltaY = curr.y - last.y;
                    float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);
                    float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight *   saveScale);
                    matrix.postTranslate(fixTransX, fixTransY);
                    fixTrans();
                    last.set(curr.x, curr.y);
                }
                break;

            case MotionEvent.ACTION_UP:
                mode = NONE;
                int xDiff = (int) Math.abs(curr.x - start.x);
                int yDiff = (int) Math.abs(curr.y - start.y);
                if (xDiff < CLICK && yDiff < CLICK)
                    performClick();
                break;

            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
        }

        setImageMatrix(matrix);
        invalidate();
        return true; // indicate event was handled
    }

      });
    }

   public void setMaxZoom(float x) {
   maxScale = x;
   }
   public float getMaxScale() {
   return maxScale;
    }

   private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
   @Override
   public boolean onScaleBegin(ScaleGestureDetector detector) {
    mode = ZOOM;
    return true;
    }

   @Override
public boolean onScale(ScaleGestureDetector detector) {
    float mScaleFactor = detector.getScaleFactor();
    float origScale = saveScale;
    saveScale *= mScaleFactor;
    if (saveScale > maxScale) {
        saveScale = maxScale;
        mScaleFactor = maxScale / origScale;
    } else if (saveScale < minScale) {
        saveScale = minScale;
        mScaleFactor = minScale / origScale;
    }

    if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)
        matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);
    else
        matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());

    fixTrans();
    return true;
    }
    }

   void fixTrans() {
 matrix.getValues(m);
float transX = m[Matrix.MTRANS_X];
float transY = m[Matrix.MTRANS_Y];

float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);

if (fixTransX != 0 || fixTransY != 0)
    matrix.postTranslate(fixTransX, fixTransY);
  }

 float getFixTrans(float trans, float viewSize, float contentSize) {
float minTrans, maxTrans;

if (contentSize <= viewSize) {
    minTrans = 0;
    maxTrans = viewSize - contentSize;
} else {
    minTrans = viewSize - contentSize;
    maxTrans = 0;
}

if (trans < minTrans)
    return -trans + minTrans;
if (trans > maxTrans)
    return -trans + maxTrans;
return 0;
  }

 float getFixDragTrans(float delta, float viewSize, float contentSize) {
if (contentSize <= viewSize) {
    return 0;
}
return delta;
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = MeasureSpec.getSize(widthMeasureSpec);
viewHeight = MeasureSpec.getSize(heightMeasureSpec);

//
// Rescales image on rotation
//
if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
        || viewWidth == 0 || viewHeight == 0)
    return;
oldMeasuredHeight = viewHeight;
oldMeasuredWidth = viewWidth;

if (saveScale == 1) {
    //Fit to screen.
    float scale;

    Drawable drawable = getDrawable();
    if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)
        return;
    int bmWidth = drawable.getIntrinsicWidth();
    int bmHeight = drawable.getIntrinsicHeight();

    Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);

    float scaleX = (float) viewWidth / (float) bmWidth;
    float scaleY = (float) viewHeight / (float) bmHeight;
    scale = Math.min(scaleX, scaleY);
    matrix.setScale(scale, scale);

    // Center the image
    float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);
    float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);
    redundantYSpace /= (float) 2;
    redundantXSpace /= (float) 2;

    matrix.postTranslate(redundantXSpace, redundantYSpace);

    origWidth = viewWidth - 2 * redundantXSpace;
    origHeight = viewHeight - 2 * redundantYSpace;
    setImageMatrix(matrix);
    }
  fixTrans();
   }
}

 replace your imageview in xml as:
  <package name.TouchImageView
   android:id="@+id/imageView2"
    ............
   />

 Hope this works..

 TouchImageView image2 = (TouchImageView)this.findViewById(R.id.imageView2);