멀티터치를 이용해서 이미지를 확대, 축소, 이동을 하려고 합니다.

 

구현은 해보았는데 문제가 이미지 사이즈 지정에 관련된 문제가 생겨 질문 드립니다.

 

matrix를 이용해서 scale시켜 확대/축소를 하는데 확대하거나 축소할경우 layout에 지정된 width와 height가 바뀌지 않아 문제가 발생하고 있습니다.

 

혹시 저와 같은 문제로 고생하셨거나 팁을 알고 계시다면 좀 알려주세요..ㅠㅠ

 

소스는 다음과 같습니다.




java파일입니다.

public class test extends Activity {


	// 올려서 가지고 놀 이미지 뷰들...
	private ImageView img1;
	private ImageView img2;
	private ImageView img3;
	private FrameLayout layout;
	// 선택 이미지.
	private ImageView selectImage;
	
	// 마우스 관련========
	private int preX; // pre좌표.
	private int preY;
	private int x; // now좌표.
	private int y;
	private int selX; // select 시의 좌표.
	private int selY;
	
	private int tx; // 움직인 거리 계산용.
	private int ty;
	
	private int allowGap = 3; // 소량의 흔들림 무시용
	
	
	private Matrix mMatrix;
	private Matrix savedMatrix;
	private float oldDistance = 0.0F;
	private boolean isScrolling = false;
	private float distanceThreshold = 3.0F;


	private float scaleRatio;
	private float totalScaleRatio;
	private float bitmapCenterX;
	private float bitmapCenterY;
	
	
	public static float MAX_SCALE_RATIO = 5.0F;
    public static float MIN_SCALE_RATIO = 0.1F;
    
	
	// 각각의 이미지는 각각의 ImageView 에 올라가있다.
	// 귀차니즘으로 그냥 ImageView 에 src를 지정해 놓았다.
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        layout = (FrameLayout)findViewById(R.id.layout_img);
        img1 = (ImageView)findViewById(R.id.img1);
        img1.setOnTouchListener(touchListener);


        img2 = (ImageView)findViewById(R.id.img2);
        img2.setOnTouchListener(touchListener);


        img3 = (ImageView)findViewById(R.id.img3);
        img3.setOnTouchListener(touchListener);
        
        selectImage = null;
        mMatrix = new Matrix();
        savedMatrix = new Matrix();
        scaleRatio = 1.0F;
        totalScaleRatio = 1.0F;
        img1.setScaleType(ScaleType.MATRIX);
        img2.setScaleType(ScaleType.MATRIX);
        img3.setScaleType(ScaleType.MATRIX);


        // 이미지 정보를 보기위한 버튼들...
        findViewById(R.id.btn1).setOnClickListener(clickListener);
        findViewById(R.id.btn2).setOnClickListener(clickListener);
        findViewById(R.id.btn3).setOnClickListener(clickListener);
        findViewById(R.id.btn4).setOnClickListener(clickListener);
    }
    
    // 버튼은 해당이미지의 위치정보를 보기위해 만들었다. 워낙에 움직임이=============================
    public void view_coordinate(ImageView v){
    	String imgname = "";
    	switch(v.getId()){
    	case R.id.img1:
    		imgname = "Image1";
    		break;
    	case R.id.img2:
    		imgname = "Image2";
    		break;
    	case R.id.img3:
    		imgname = "Image3";
    		break;
    	}
    	toMessage(
    		imgname + " 좌표: (" + v.getLeft() + ", " + v.getTop()
    		+ ", " + v.getRight() + ", " + v.getBottom() + ")"
    	);
    }
    
    View.OnClickListener clickListener = new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.btn1:
				view_coordinate(img1);
				break;
			case R.id.btn2:
				view_coordinate(img2);
				break;
			case R.id.btn3:
				view_coordinate(img3);
				break;
			case R.id.btn4:
				toMessage("미안 귀찮아서 리셋구현 안했어...");
				break;
			default:
				break;
			}
		}
	};
    
	// 터치리스너========================================================
    View.OnTouchListener touchListener = new View.OnTouchListener() {


    	@Override
		public boolean onTouch(View v, MotionEvent event) {
    		// 이 좌표는 뷰의 이벤트로 받아오는 좌표라서
    		// 선택된 뷰의 지역좌표가 된다.
    		// ImageView 가 FrameLayout의 어디에 있더라도 ImageView 의 좌상단을 터치했다면 (0,0) 이다. 그렇다. ㅠ.ㅠ
    		// 마우스를 휙~~ 움직이면 -(마이너스)값이 나오기도 한다.


			x = (int)event.getX();
			y = (int)event.getY();
			Log.i("touch", "x : "+(int)event.getX() + " y : " + (int)event.getY());
    		int count = event.getPointerCount();
			Log.i("touch", "count = " + count + " : " + event.getAction());
			switch ( event.getAction() ) {
	    		case MotionEvent.ACTION_DOWN:
	    			
	    			if(selectImage == null){
	    				// 터치하면 터치한 뷰와 터치좌표를 저장한다.
	    				selectImage = (ImageView)v;
		        		selectImage.bringToFront();
		        		savedMatrix.set(mMatrix);
		        		selX = preX = x;
		        		selY = preY = y;
		    			return true;
	    			}
	    			


	    		case MotionEvent.ACTION_POINTER_2_DOWN:
	    			Log.i("touch", "down count = 2");
    				oldDistance = 0.0F;
        			savedMatrix.set(mMatrix);
        			isScrolling = true;
        			
        			break;
	    		case MotionEvent.ACTION_MOVE:
	    			if(selectImage == (ImageView)v && count == 1){
		    			tx = x - preX;
		    			ty = y - preY;


		    			// 이 if문의 존재 이유는 터치하고 가만있어도 1,2 픽셀씩 흔들리는 움직임을 잡기 위해서다.
		    			// 손가락 터치로 한픽셀만 터치한다는건 불가능할테니 당연한 흔들림일것이다.
		    			if(  ((tx > -allowGap) && (tx < allowGap)) && ((ty > -allowGap) && (ty < allowGap))  ){
			        		return false;
		    			}else{
		    				tx = x - selX;
		    				ty = y - selY;
		    				selectImage.layout(selectImage.getLeft() + tx, selectImage.getTop() + ty,
		    						selectImage.getRight() + tx, selectImage.getBottom() + ty);


		    				preX = x;
		    				preY = y;


			        		return true;
		    			}
	    			}if (count == 2) {
	    				Log.i("touch", "move count = 2");
	    				Log.i("touch", "x1:" + event.getX(0) + " x2:"+event.getX(1));


	    	    		float x1 = event.getX(0);
	    	    		float y1 = event.getY(0);
	    	    		float x2 = event.getX(1);
	    	    		float y2 = event.getY(1);
	    	    		
	    	    		float dx = x1 - x2;
	    	    		float dy = y1 - y2;
	    	    		float distance = FloatMath.sqrt(dx * dx + dy * dy);
	    	    		float outScaleRatio = 0.0F;
	    	    		if (oldDistance == 0.0F) {
	    	    			oldDistance = distance;
	    	    			
	    	    			break;
	    	    		}
	    	    		
	    	    		if (distance > oldDistance) {
	    	    			if ((distance-oldDistance) < distanceThreshold) {
	    	    				return true;
	    	    			}


	    	    			outScaleRatio = scaleRatio + (oldDistance / distance * 0.05F);
	    	    		} else if (distance < oldDistance) { 
	    	    			if ((oldDistance-distance) < distanceThreshold) {
	    	    				return true;
	    	    			}


	    	    			outScaleRatio = scaleRatio - (distance / oldDistance * 0.05F);
	    	    		}


	    	    		if (outScaleRatio < MIN_SCALE_RATIO || outScaleRatio > MAX_SCALE_RATIO) {
	                    } else {
//	                    	int w;
//	                    	int h;
//	                    	
//	                    	switch(v.getId()){
//	                    	case R.id.img1:
//	                    		w = (int) ((int)img1.getWidth()*outScaleRatio);
//	                    		h = (int) ((int)img1.getHeight()*outScaleRatio);
//	                    		img1.setLayoutParams(new Gallery.LayoutParams(w,h));
//	                    		break;
//	                    	case R.id.img2:
//	                    		w = (int) ((int)img2.getWidth()*outScaleRatio);
//	                    		h = (int) ((int)img2.getHeight()*outScaleRatio);
//	                    		img2.setLayoutParams(new Gallery.LayoutParams(w,h));
//	                    		break;
//	                    	case R.id.img3:
//	                    		w = (int) ((int)img3.getWidth()*outScaleRatio);
//	                    		h = (int) ((int)img3.getHeight()*outScaleRatio);
//	                    		img3.setLayoutParams(new Gallery.LayoutParams(w,h));
//
//	                    	}
	                        scaleImage(outScaleRatio);
	                        selectImage.setImageMatrix(mMatrix);
	                        selectImage.invalidate();
	                    }
	    	    		
	    	    		oldDistance = distance;
	    	    	}
	    			break;
	    		case MotionEvent.ACTION_UP:
	    			if(selectImage != null){
	    				selectImage = null;
	    				isScrolling = false;
	    				return true;
	    			}
	    			break;
			}//switch
			return true;
		}//public boolean onTouch(View v, MotionEvent event) {
	};//View.OnTouchListener touchListener = new View.OnTouchListener() {
	
	
	
	private void scaleImage(float inScaleRatio) {
    	Log.d("touch", "scaleImage() called : " + inScaleRatio);


    	mMatrix.postScale(inScaleRatio, inScaleRatio, bitmapCenterX, bitmapCenterY);
    	mMatrix.postRotate(0);


    	totalScaleRatio = totalScaleRatio * inScaleRatio;


     }
	
	
		
    // 메세지 출력용 ================================
	Toast tempToast;
    public void toMessage(String str){
    	if(tempToast==null){
    		tempToast = Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG);
    	}else{
    		tempToast.setText(str);
    	}
    	tempToast.show();
    }


    public void toAlert(String str){
    	new AlertDialog.Builder(getApplicationContext())
    	.setMessage(str)
    	.setCancelable(false)
    	.setNegativeButton("닫기", null)
    	.show();
    }




xml 파일입니다.








<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:orientation="vertical"
	>
	<LinearLayout
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:orientation="horizontal"
		android:gravity="center"
		>
		<Button
			android:id="@+id/btn1"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="1번"
			/>
		<Button
			android:id="@+id/btn2"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="2번"
			/>
		<Button
			android:id="@+id/btn3"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="3번"
			/>
		<Button
			android:id="@+id/btn4"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="리셋"
			/>
	</LinearLayout>
	<FrameLayout
		android:id="@+id/layout_img"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		>
		<ImageView 
			android:id="@+id/img1"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:src="@drawable/image1"
		/>
		<ImageView 
			android:id="@+id/img2"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:src="@drawable/image2"
		/>
		<ImageView 
			android:id="@+id/img3"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:src="@drawable/image3"
		/>
	</FrameLayout>
</LinearLayout>


공지사항 다 읽었습니다!