2014-10-07 42 views
0

我用下面的代码添加捏缩放和平移当使用ImageView的子类,双指缩放的很慢的性能

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

+0

我刚刚注意到,只要子类不覆盖onDraw,整个过程就是平滑的。添加覆盖会让事情再次变得缓慢! – dna 2014-10-07 10:10:16

回答

0

创建自定义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); 
+0

感谢您的关注。我试过这个..但是表现仍然是一样的..在放大和移动时滞后时间.. LogCat也显示一条消息:10-07 07:19:50.670:I/Choreographer(1250):跳过了366帧!应用程序可能在其主线程上做了太多工作。该活动没有其他任何东西..只是这个TouchImageView ..来测试它是如何工作的。 – dna 2014-10-07 07:24:27

+0

XML文件: dna 2014-10-07 07:37:28