안드로이드 개발 질문/답변
(글 수 45,052)
멀티터치를 이용해서 이미지를 확대, 축소, 이동을 하려고 합니다.
구현은 해보았는데 문제가 이미지 사이즈 지정에 관련된 문제가 생겨 질문 드립니다.
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>
공지사항 다 읽었습니다!



