스마트기기개발관련/안드로이드 개발

안드로이드 이미지 뷰어 멀티 터치 줌 관련

AlrepondTech 2011. 7. 14. 11:21
반응형

 



=======================

=======================

=======================

 

 

 

 

 

 

 

출처: http://blog.naver.com/PostView.nhn?blogId=wono77&logNo=140111681477&viewDate=&currentPage=1&listtype=0

Touchv1.zip
다운로드
touch_psjFix.zip
다운로드

안드로이드 멀티터치줌 (Multitouch Zoom)

 

최초 정리 시작: 2010년 7월 28일

최종 정리 by wono77(20101005)

 

안드로이드에서 이미지를 멀티터치줌 하는 방법에 대해 설명해둔 외국글, 그리고 소스를 소개합니다.

6개의 파트로 글이 나눠어져 있습니다.

(멀티터치줌 테스트는 에뮬에서 안되니 실제 폰에 올려서 테스트하세요.^^)

 

블로그에 소스 파일 첨부합니다.

 

링크: http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2/1747?tag=rbxccnbzd1

 

소스는 이 사람책인 HelloAndroid 3rd Edtion사이트에서 받으면 됩니다.

http://pragprog.com/titles/eband3/hello-android

http://pragprog.com/titles/eband3/source_code

 

그외 참고할 만한 멀티터치줌 관련 사이트:

 

* 안드로이드 공식 블로그:

http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html

* 소니에릭슨 사이트:

http://blogs.sonyericsson.com/developerworld/category/tutorials/zoom/

 

> 그 중 첫 번째 글:

 

Introducing multi-touch

Multi-touch is simply an extension of the regular touch-screen user interface, using two or more fingers instead of one. We’ve used single-finger gestures before, although we didn’t call it that. In Chapter 4 we let the user touch a tile in the Sudoku game in order to change it. That’s called a “tap” gesture. Another gesture is called “drag”. That’s where you hold one finger on the screen and move it around, causing the content under your finger to scroll.

Tap, drag, and a few other single-fingered gestures have always been supported in Android. But due to the popularity of the Apple iPhone, early Android users suffered from a kind of gesture envy. The iPhone supported multi-touch, in particular the “pinch zoom” gesture.

 

Three common touch gestures: a) tap, b) drag, and c) pinch zoom. (Image courtesy of GestureWorks.com)

 

With pinch zoom, you place two fingers on the screen and squeeze them together to make the item you’re viewing smaller, or pull them apart to make it bigger. Before Android 2.0 you had to use a clunky zoom control with icons that you pressed to zoom in and out (for example the setBuiltInZoomControls() in the MyMap example). But thanks to its new multi-touch support, you can now pinch to zoom on Android too! As long as the application supports it, of course.

Note: If you try to run the example in this chapter on Android 1.5 or 1.6, it will crash because those versions do not support multi-touch. We’ll learn how to work around that in chapter 13, “Write Once, Test Everywhere”.

Warning: Multi-bugs ahead

Multi-touch, as implemented on current Android phones is extremely buggy. In fact it’s so buggy that it borders on the unusable. The API routinely reports invalid or impossible data points, especially during the transition from one finger to two fingers on the screen and vice-versa.

On the developer forums you can find complaints of fingers getting swapped, x and y axes flipping, and multiple fingers sometimes being treated as one. With a lot of trial and error, I was able to get the example in this chapter working because the gesture it implements is so simple. Until Google acknowledges and fixes the problems, thatmay be about all you can do. Luckily, pinch zoom seems to be the only multi-touch gesture most people want.

The Touch example

To demonstrate multi-touch, we’re going to build a simple image viewer application that lets you zoom in and scroll around an image. Here’s a screenshot of the finished product:

 

The Touch example implements a simple image viewer with drag and pinch zoom.

 

Continue reading: Part 2: Building the Touch Example >

 
 



=======================

=======================

=======================

 

 




출처: http://blog.flysky.kr/blog/4547416



10. 8. 6. 11:00 - 확대/축소 오작동을 잡았습니다.
10. 8. 6. 20:00 - 처음 나타날 때, 이미지를 변경할 때 작은 이미지는 가운데, 큰 이미지는 크기에 맞게 축소해서 나오도록 함.
10. 8. 9. 18:00 - 소속된 화면에 변경이 생기면 크기가 리셋되는 문제 수정함.

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;


public class ViewTouchImage extends ImageView implements OnTouchListener{
    // 디버깅 정보
    private static final String TAG = "ViewTouchImage";
    private static final boolean D = false;
    
    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();
    private Matrix savedMatrix2 = new Matrix();
    
    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;
    
    private PointF start = new PointF();
    private PointF mid = new PointF();
    private float oldDist = 1f;
    
    private static final int WIDTH = 0;
    private static final int HEIGHT = 1;
    
    private boolean isInit = false;
    
    public ViewTouchImage(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        
        setOnTouchListener(this);
        setScaleType(ScaleType.MATRIX);
    }

    public ViewTouchImage(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ViewTouchImage(Context context) {
        this(context, null);
    }

    
    
    

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        if (D) Log.i(TAG, "onLayout");
        super.onLayout(changed, left, top, right, bottom);
        if (isInit == false){
            init();
            isInit = true;
        }
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        if (D) Log.i(TAG, "setImageBitmap");
        super.setImageBitmap(bm);
        isInit = false;
        init();
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        if (D) Log.i(TAG, "setImageDrawable");
        super.setImageDrawable(drawable);
        isInit = false;
        init();
    }

    @Override
    public void setImageResource(int resId) {
        if (D) Log.i(TAG, "setImageResource");
        super.setImageResource(resId);
        isInit = false;
        init();
    }

    protected void init() {
        matrixTurning(matrix, this);
        setImageMatrix(matrix);
        setImagePit();
    }

    /**
     * 이미지 핏
     */
    public void setImagePit(){
        
        // 매트릭스 값
        float[] value = new float[9];
        this.matrix.getValues(value);
        
        // 뷰 크기
        int width = this.getWidth();
        int height = this.getHeight();
        
        
        // 이미지 크기
        Drawable d = this.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]);
        
       // 이미지가 바깥으로 나가지 않도록.

        value[2] = 0;
        value[5] = 0;
        
        if (imageWidth > width || imageHeight > 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;
        }
        
        // 그리고 가운데 위치하도록 한다.
        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);
        
        setImageMatrix(matrix);
    }
    
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        ImageView view = (ImageView) v;

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
           savedMatrix.set(matrix);
           start.set(event.getX(), event.getY());
           mode = DRAG;
           break;
        case MotionEvent.ACTION_POINTER_DOWN:
           oldDist = spacing(event);
           if (oldDist > 10f) {
              savedMatrix.set(matrix);
              midPoint(mid, event);
              mode = ZOOM;
           }
           break;
       case MotionEvent.ACTION_UP:

        case MotionEvent.ACTION_POINTER_UP:
           mode = NONE;
           break;
        case MotionEvent.ACTION_MOVE:
           if (mode == DRAG) {
              matrix.set(savedMatrix);
             matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);

           }
           else if (mode == ZOOM) {
              float newDist = spacing(event);
              if (newDist > 10f) {
                 matrix.set(savedMatrix);
                 float scale = newDist / oldDist;
                 matrix.postScale(scale, scale, mid.x, mid.y);
              }
           }
           break;
        }

        // 매트릭스 값 튜닝.
        matrixTurning(matrix, view);
        
        view.setImageMatrix(matrix);
        
        return true;
    }
    
    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;
        
        // 10배 이상 확대 하지 않도록
        if (value[0] > 10 || value[4] > 10){
            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);
    }
}

 

 



=======================

=======================

=======================

 

 

반응형