package com.example.zoominzoomout6;
import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
public class MainActivity extends Activity implements OnTouchListener {
 // These matrices will be used to move and zoom image
 Matrix matrix = new Matrix();
 Matrix savedMatrix = new Matrix();
 Matrix savedMatrix2 = new Matrix(); 
 private static final String TAG = "Touch" ; 
 // 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;  
    private static final int WIDTH = 0;
    private static final int HEIGHT = 1; 
 //Remeber some things for zooming
 PointF start = new PointF();
 PointF mid = new PointF();
 float oldDist = 1f;
 ImageView view = null;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       view = (ImageView) findViewById(R.id.imgView1); 
        view.setOnTouchListener(this);
         
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
 public boolean onTouch(View v, MotionEvent event) {
  // TODO Auto-generated method stub 
  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_UP://터치종료(첫번째 터치)
   case MotionEvent.ACTION_POINTER_UP://터치종료(두번째 터치)
   mode = NONE;
   Log.d(TAG, "mode=NONE" );
   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_MOVE://드래그 중
     
   if (mode == DRAG) {
    matrix.set(savedMatrix);
    float tx = event.getX() - start.x;
    float ty = event.getY() - start.y;
    Log.i("msg", "tx,ty\t"+tx+", "+ty);
 
    /*
    float[] value = new float[9];
    matrix.getValues(value);
    // 이미지 크기
    Drawable d = view.getDrawable();
    if (d == null)  break;
    int imageWidth = d.getIntrinsicWidth();
    int imageHeight = d.getIntrinsicHeight();
    int scaleWidth = (int) (imageWidth * value[0]);
    int scaleHeight = (int) (imageHeight * value[4]);
   */
         //if((tx<-14&ty<77)|(tx<3.9&ty<-53)){
     matrix.postTranslate(tx, ty);
    //}
         
   }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);
    } 
    float[] values = new float[9]; 
          matrix.getValues(values); 
  
    // 매트릭스 값 튜닝.
          matrixTurning(matrix, view);
   }
   break;
   
  } 
  // Perform the transformation
  view.setImageMatrix(matrix);  
  return true; // indicate event was handled
 } 
 
   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); 
   }
   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);
   }
   
   private void matrixTurning(Matrix matrix, ImageView view){
       // 매트릭스 값
       float[] value = new float[9];
       matrix.getValues(value);
       float[] savedValue = new float[9];
       savedMatrix2.getValues(savedValue); 
       // 뷰 크기
       int width = view.getWidth();
       int height = view.getHeight();
       
       // 이미지 크기
       Drawable d = view.getDrawable();
       if (d == null)  return;
       int imageWidth = d.getIntrinsicWidth();
       int imageHeight = d.getIntrinsicHeight();
       int scaleWidth = (int) (imageWidth * value[0]);
       int scaleHeight = (int) (imageHeight * value[4]);
       
       // 이미지가 바깥으로 나가지 않도록.
       if (value[2] < width - scaleWidth)   value[2] = width - scaleWidth;
       if (value[5] < height - scaleHeight)   value[5] = height - scaleHeight;
       if (value[2] > 0)   value[2] = 0;
       if (value[5] > 0)   value[5] = 0;
       
       // 5배 이상 확대 하지 않도록
       if (value[0] > 5 || value[4] > 5){
           value[0] = savedValue[0];
           value[4] = savedValue[4];
           value[2] = savedValue[2];
           value[5] = savedValue[5];
       }
       
       // 화면보다 작게 축소 하지 않도록 
       if (imageWidth > width || imageHeight > height){
           if (scaleWidth < width && scaleHeight < height){
               int target = WIDTH;
               if (imageWidth < imageHeight) target = HEIGHT;
               
               if (target == WIDTH) value[0] = value[4] = (float)width / imageWidth;
               if (target == HEIGHT) value[0] = value[4] = (float)height / imageHeight;
               
               scaleWidth = (int) (imageWidth * value[0]);
               scaleHeight = (int) (imageHeight * value[4]);
               
               if (scaleWidth > width) value[0] = value[4] = (float)width / imageWidth;
               if (scaleHeight > height) value[0] = value[4] = (float)height / imageHeight;
           }
       }
       
       // 원래부터 작은 얘들은 본래 크기보다 작게 하지 않도록
       else{
           if (value[0] < 1)   value[0] = 1;
           if (value[4] < 1)   value[4] = 1;
       }
       
       // 초기위치를  가운데로 한다.
       scaleWidth = (int) (imageWidth * value[0]);
       scaleHeight = (int) (imageHeight * value[4]);
       if (scaleWidth < width){
           value[2] = (float) width / 2 - (float)scaleWidth / 2;
       }
       if (scaleHeight < height){
           value[5] = (float) height / 2 - (float)scaleHeight / 2;
       }
       
       matrix.setValues(value);
       savedMatrix2.set(matrix);
   }
}
xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <ImageView
        android:id="@+id/imgView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/a"
        android:scaleType="matrix" 
        android:background="@drawable/bg_wood"
        />
</RelativeLayout>

위 소스를 실행하면 이미지 확대 및 축소가 되고, 이미지 이동도 됩니다.

근데 첫화면에서 이미지가 크게 확대된 채로 표시됩니다.

첫화면에서 이미지를 한눈에 볼 수 있게 작게 표시하는 방법을 알고 싶습니다.

 

그리고 이미지가 이동이 되긴하는데 범위의 제한이 없어서 끝 없이 이동이 됩니다.

예를들어 계속 좌로 움직이면 계속해서 무한대로 좌측으로 움직일 수 있습니다.

이미지가 화면에 표시되지 않아도 말이죠.

 

이미지가 화면에 표시되는 영역까지만 이동이 되게 하고 싶습니다.

그러니까 이동이 되는 거리는 얼만큼 확대 했느냐에 따라 달라질 것이고

또 얼만큼 축소 했느냐에 따라 또 변하겠죠.

스케일 값을 가지고 어떻게 조건을 걸어주면 될 것 같은데, 쉽게 생각이 나질 않네요.

 

여러분께 두가지 도움을 요청합니다.

그럼, 오늘도 즐거운 하루 보내세요~^^