멀티터치 예제를 구해서 공부하는 중에 화면이동에 대해 문제가 생겨서 고민하다가 질문을 올립니다.

 

출력되는 결과를 화면 사이즈에 맞게 출력해주고(ex: 480X800) 그 안에서 확대되고 축소되게 하고 싶은데,

제가 구한 예제에서는 화면을 끝없이 이동하게 됩니다. 정신과 시간의 방처럼

 

소스 TouchExampleView.java의 GestureCallback클래스에서 mPosX와 mPosY를 다음과 같이,

 

if(mPosX > 0) {
     mPosX = 0;
    }

...

if(mPosY > 0) {
     mPosY = 0;
    }

 

이렇게 하니까 화면의 위와 왼쪽은 막히는데...아래와 오른쪽이 문제입니다. 같은 방법으로 막으면

확대했을 때 이동이 안됩니다. ㅜㅠ

 

이동할 수 있는 범위를 화면 크기에 맞게 할 수 있는 방법을 알고싶습니다.

고수님들 가르침을 주시면 감사하겠습니다.

소스는 다음과 같습니다.(출처: http://code.google.com/p/android-touchexample/ )

 

 

MainActivity.java

 package com.example.zoomout; 

import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup;

public class MainActivity extends Activity {
 /** Called when the activity is first created. */
 
 @Override    
 public void onCreate(Bundle savedInstanceState) {  
  super.onCreate(savedInstanceState);
  TouchExampleView view = new TouchExampleView(this);
  view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 
    ViewGroup.LayoutParams.MATCH_PARENT));
  setContentView(view); 
 } 
 }


TouchExampleView.java

 package com.example.zoomout;
import android.content.Context; 
import android.graphics.Canvas;
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.view.MotionEvent;
import android.view.View; 
public class TouchExampleView extends View {
 private Drawable mIcon;  
 private float mPosX;  
 private float mPosY;  
 private VersionedGestureDetector mDetector; 
 private float mScaleFactor = 1.f; 

 public TouchExampleView(Context context) {   
  this(context, null, 0);
  }        
 public TouchExampleView(Context context, AttributeSet attrs) {  
  this(context, attrs, 0); 
  }      
 public TouchExampleView(Context context, AttributeSet attrs, int defStyle) { 
  super(context, attrs, defStyle); 
  mIcon = context.getResources().getDrawable(R.drawable.icon);
  mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight());
  mDetector = VersionedGestureDetector.newInstance(context, new GestureCallback()); 
  }         
 @Override 
 public boolean onTouchEvent(MotionEvent ev) {
  mDetector.onTouchEvent(ev);
  return true; 
  }    
 @Override   
 public void onDraw(Canvas canvas) { 
  super.onDraw(canvas); 
  canvas.save();      
  canvas.translate(mPosX, mPosY);  
  canvas.scale(mScaleFactor, mScaleFactor);
  mIcon.draw(canvas); 
  canvas.restore();   
  }    
 private class GestureCallback implements VersionedGestureDetector.OnGestureListener { 
  public void onDrag(float dx, float dy) {  
   mPosX += dx;
   mPosY += dy;
   invalidate();   
   }    
  public void onScale(float scaleFactor) {
   mScaleFactor *= scaleFactor;  
   // Don't let the object get too small or too large.
   mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 3.0f)); 
   invalidate();    
  } 
 }
}

VersionedGestureDetector.java

 package com.example.zoomout;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.view.MotionEvent; 
import android.view.ScaleGestureDetector; 
public abstract class VersionedGestureDetector {
 private static final String TAG = "VersionedGestureDetector";
 OnGestureListener mListener;   
 @SuppressWarnings("deprecation")
 public static VersionedGestureDetector newInstance(Context context,   
   OnGestureListener listener) {  
  final int sdkVersion = Integer.parseInt(Build.VERSION.SDK); 
  VersionedGestureDetector detector = null;  
  if (sdkVersion < Build.VERSION_CODES.ECLAIR) {  
   detector = new CupcakeDetector();   
   } else if (sdkVersion < Build.VERSION_CODES.FROYO) {
    detector = new EclairDetector(); 
    } else {    
     detector = new FroyoDetector(context);  
     } 
  Log.d(TAG, "Created new " + detector.getClass()); 
  detector.mListener = listener;  
  return detector;
  }     
 public abstract boolean onTouchEvent(MotionEvent ev);  
 public interface OnGestureListener {  
  public void onDrag(float dx, float dy); 
  public void onScale(float scaleFactor);
  }     
 private static class CupcakeDetector extends VersionedGestureDetector { 
  float mLastTouchX; 
  float mLastTouchY; 
  float getActiveX(MotionEvent ev) {
   return ev.getX();       
   }      
  float getActiveY(MotionEvent ev) {  
   return ev.getY();  
   }             
  boolean shouldDrag() { 
           return true;      
           }    
  @Override      
  public boolean onTouchEvent(MotionEvent ev) { 
   switch (ev.getAction()) {
   case MotionEvent.ACTION_DOWN: {   
    mLastTouchX = getActiveX(ev); 
    mLastTouchY = getActiveY(ev); 
    break;        
    }       
   case MotionEvent.ACTION_MOVE: {  
    final float x = getActiveX(ev);  
    final float y = getActiveY(ev);
    if (shouldDrag()) {    
     mListener.onDrag(x - mLastTouchX, y - mLastTouchY);
     }
    mLastTouchX = x;
    mLastTouchY = y;  
    break;      
    }          
   }        
   return true; 
   }   
  }  
 private static class EclairDetector extends CupcakeDetector { 
  private static final int INVALID_POINTER_ID = -1; 
  private int mActivePointerId = INVALID_POINTER_ID; 
  private int mActivePointerIndex = 0;       
  @Override       
  float getActiveX(MotionEvent ev) {  
   return ev.getX(mActivePointerIndex); 
   }        
  @Override   
  float getActiveY(MotionEvent ev) {   
   return ev.getY(mActivePointerIndex); 
   }        
  @Override
  public boolean onTouchEvent(MotionEvent ev) { 
   final int action = ev.getAction(); 
   switch (action & MotionEvent.ACTION_MASK) {  
   case MotionEvent.ACTION_DOWN:     
    mActivePointerId = ev.getPointerId(0); 
    break;          
    case MotionEvent.ACTION_CANCEL:  
     case MotionEvent.ACTION_UP: 
      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; 
    mActivePointerId = ev.getPointerId(newPointerIndex); 
    mLastTouchX = ev.getX(newPointerIndex); 
    mLastTouchY = ev.getY(newPointerIndex);
    }        
   break;  
   }      
   mActivePointerIndex = ev.findPointerIndex(mActivePointerId);   
   return super.onTouchEvent(ev);  
   }    
  }     
 private static class FroyoDetector extends EclairDetector {
  private ScaleGestureDetector mDetector; 
  public FroyoDetector(Context context) {  
   mDetector = new ScaleGestureDetector(context,  
     new ScaleGestureDetector.SimpleOnScaleGestureListener() {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {  
     mListener.onScale(detector.getScaleFactor());  
     return true;     
     }         
    });   
   }   
  @Override   
  boolean shouldDrag() {  
   return !mDetector.isInProgress(); 
   }          
  @Override    
  public boolean onTouchEvent(MotionEvent ev) { 
   mDetector.onTouchEvent(ev); 
   return super.onTouchEvent(ev); 
   }  
  }
 } 

공지사항 다 읽었습니다. 감사합니다.