2011-09-20 4 views
5

나는 잘 작동하는 TouchImageView가 있는데 코드에서 어떻게 작동하는지 알고 싶습니다. 내가 원하는 것은 확대/축소하거나 두 번 탭하여 선택한 모든 imageview를 확대/축소 할 수 있습니다. 뒤로 축소하면 이미지의 원래 크기로 돌아갑니다. TouchImageView.java :() 나는 createUrlImage (URL)를 넣어TouchImageView는 어떻게 작동합니까?

private class CreateImage extends AsyncTask<String, Void, Drawable> { 
    protected void onPreExecute() { 
    } 

    protected Drawable doInBackground(String... urls) { 
     InputStream is; 
     Drawable d = null ; 
     try { 
      is = (InputStream)new URL(urls[0]).getContent(); 
      d = Drawable.createFromStream(is, "Image"); 
      return d; 
     } catch (MalformedURLException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return d; 
    } 
    protected void onPostExecute(Drawable d) { 
     touch.setMaxZoom(4f); 
     touch.setImageDrawable(d); 
     setContentView(touch); 
    } 
} 
public void createUrlImage(String url){ 
    new CreateImage().execute(url); 
} 

과에서 onCreate에서 :

public class TouchImageView extends ImageView { 

Matrix matrix = new Matrix(); 

static final int NONE = 0; 
static final int DRAG = 1; 
static final int ZOOM = 2; 
int mode = NONE; 

PointF last = new PointF(); 
PointF start = new PointF(); 
float minScale = 1f; 
float maxScale = 3f; 
float[] m; 

float redundantXSpace, redundantYSpace; 

float width, height; 
static final int CLICK = 3; 
float saveScale = 1f; 
float right, bottom, origWidth, origHeight, bmWidth, bmHeight; 

ScaleGestureDetector mScaleDetector; 

Context context; 


public TouchImageView(Context context) { 
super(context); 
super.setClickable(true); 
this.context = context; 
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
matrix.setTranslate(1f, 1f); 
m = new float[9]; 
setImageMatrix(matrix); 
setScaleType(ScaleType.MATRIX); 

setOnTouchListener(new OnTouchListener() { 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     mScaleDetector.onTouchEvent(event); 

     matrix.getValues(m); 
     float x = m[Matrix.MTRANS_X]; 
     float y = m[Matrix.MTRANS_Y]; 
     PointF curr = new PointF(event.getX(), event.getY()); 

     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       last.set(event.getX(), event.getY()); 
       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 scaleWidth = Math.round(origWidth * saveScale); 
        float scaleHeight = Math.round(origHeight * saveScale); 
        if (scaleWidth < width) { 
         deltaX = 0; 
         if (y + deltaY > 0) 
          deltaY = -y; 
         else if (y + deltaY < -bottom) 
          deltaY = -(y + bottom); 
        } else if (scaleHeight < height) { 
         deltaY = 0; 
         if (x + deltaX > 0) 
          deltaX = -x; 
         else if (x + deltaX < -right) 
          deltaX = -(x + right); 
        } else { 
         if (x + deltaX > 0) 
          deltaX = -x; 
         else if (x + deltaX < -right) 
          deltaX = -(x + right); 

         if (y + deltaY > 0) 
          deltaY = -y; 
         else if (y + deltaY < -bottom) 
          deltaY = -(y + bottom); 
        } 
        matrix.postTranslate(deltaX, deltaY); 
        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 
    } 

}); 
} 

@Override 
public void setImageBitmap(Bitmap bm) { 
super.setImageBitmap(bm); 
bmWidth = bm.getWidth(); 
bmHeight = bm.getHeight(); 
} 

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

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

@Override 
public boolean onScale(ScaleGestureDetector detector) { 
    float mScaleFactor = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05); 
    float origScale = saveScale; 
    saveScale *= mScaleFactor; 
    if (saveScale > maxScale) { 
     saveScale = maxScale; 
     mScaleFactor = maxScale/origScale; 
    } else if (saveScale < minScale) { 
     saveScale = minScale; 
     mScaleFactor = minScale/origScale; 
    } 
    right = width * saveScale - width - (2 * redundantXSpace * saveScale); 
    bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); 
    if (origWidth * saveScale <= width || origHeight * saveScale <= height) { 
     matrix.postScale(mScaleFactor, mScaleFactor, width/2, height/2); 
     if (mScaleFactor < 1) { 
      matrix.getValues(m); 
      float x = m[Matrix.MTRANS_X]; 
      float y = m[Matrix.MTRANS_Y]; 
      if (mScaleFactor < 1) { 
       if (Math.round(origWidth * saveScale) < width) { 
        if (y < -bottom) 
         matrix.postTranslate(0, -(y + bottom)); 
        else if (y > 0) 
         matrix.postTranslate(0, -y); 
       } else { 
        if (x < -right) 
         matrix.postTranslate(-(x + right), 0); 
        else if (x > 0) 
         matrix.postTranslate(-x, 0); 
       } 
      } 
     } 
    } else { 
     matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); 
     matrix.getValues(m); 
     float x = m[Matrix.MTRANS_X]; 
     float y = m[Matrix.MTRANS_Y]; 
     if (mScaleFactor < 1) { 
      if (x < -right) 
       matrix.postTranslate(-(x + right), 0); 
      else if (x > 0) 
       matrix.postTranslate(-x, 0); 
      if (y < -bottom) 
       matrix.postTranslate(0, -(y + bottom)); 
      else if (y > 0) 
       matrix.postTranslate(0, -y); 
     } 
    } 
    return true; 

} 
} 

@Override 
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) 
{ 
super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
width = MeasureSpec.getSize(widthMeasureSpec); 
height = MeasureSpec.getSize(heightMeasureSpec); 
//Fit to screen. 
float scale; 
float scaleX = (float)width/(float)bmWidth; 
float scaleY = (float)height/(float)bmHeight; 
scale = Math.min(scaleX, scaleY); 
matrix.setScale(scale, scale); 
setImageMatrix(matrix); 
saveScale = 1f; 

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

matrix.postTranslate(redundantXSpace, redundantYSpace); 

origWidth = width - 2 * redundantXSpace; 
origHeight = height - 2 * redundantYSpace; 
right = width * saveScale - width - (2 * redundantXSpace * saveScale); 
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); 
setImageMatrix(matrix); 
} 

} 

사용하려면 내가 개인 클래스를 생성합니다. 나는 추가하여 TouchImageView 수정 :

public void setImageDrawable(Drawable dr) { 
super.setImageDrawable(dr); 
bmWidth = dr.getIntrinsicWidth(); 
bmHeight = dr.getIntrinsicHeight(); 
} 

답변

6

편집 : 나는 원래이 질문에 대답하기 때문에 더블 탭 줌, 날뛰는 및 기타 기능이 TouchImageView에 추가되었습니다. github here에서 확인할 수 있습니다.


원래 게시물 here에 일부 사용법 세부 정보를 추가했습니다. 코드에는 이미 경계가있는 핀치 확대/축소 및 패닝이 있습니다. 또한 축소하면 원본 크기의 이미지로 돌아갑니다.

더블 탭 줌을 추가하면 더 많은 작업이 필요합니다. GestureDetector를 사용하고 onDoubleTap 및 onSingleTapConfirmed를 재정의해야합니다. 그런 다음 코드의 나머지 부분을 간섭하지 않고 터치 이벤트를 gestureDetector로 전달해야합니다 (onTouch 시작시 이벤트가 mScaleDetector에 전달되는 방법 참조). ACTION_UP에서 performClick()에 대한 호출을 제거하고 대신 onSingleTapConfirmed에 배치하려고합니다. 일부 골격 코드의 경우 this answer을 확인하여 GestureDetector 구현을 시작할 수 있습니다.

두 번 살짝 두드려서 확대 ​​/ 축소하면 원래 게시물과 Github 저장소에 변경 사항을 추가하겠습니다.

+0

하지만 TouchImageView를 Xml 레이아웃에 넣을 수 없습니까? – Tsunaze

+0

그리고 내가 전달하고자하는 이미지는 Asynctask에서 얻을 수있는 drawable입니다. – Tsunaze

+0

비트 맵 대신 드로어 블을 넣기 위해 약간 수정하여 작동하지만, Asynctask를 통해 드로어 블을 전달할 수는 없습니다. – Tsunaze