快速連結

2013年2月26日

改‧TouchImageView

原本我使用的版本找不到了,類似的在此:Pinching Zoom in android Image View or Bitmap
另外一個的版本則是這個:MikeOrtiz / TouchImageView
WrapMotionEvent與EclairMotionEvent程式碼我就沒有放上來了,直接到第一個連結複製即可。
我這裡參考許多文章,在TouchImageView.java內增加了放大縮小、邊界判定。



package com.bear.myclass;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;

@SuppressLint("ViewConstructor")
public class TouchImageView extends ImageView {

  private static final String TAG = "Touch";
     // These matrices will be used to move and zoom image
     Matrix matrix = new Matrix();
     Matrix savedMatrix = new Matrix();
     
     // 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;

     // Remember some things for zooming
     PointF start = new PointF();
     PointF mid = new PointF();
     float oldDist = 1f;
     
     Context context;
     View parentView;

     int frameWidth = 0;
     int frameHeight = 0;
     int bitmapWidth = 0;
     int bitmapHeight = 0;

     public int maxWidth = 0;   //放大後最大可以寬到多少
     public int minWidth = 0;   //縮小後最小可以小到多少
     float minScale = 0;
     
 
     public TouchImageView(Context context, final View parentView) {
  super(context);
  // TODO 自動產生的建構子 Stub
  super.setClickable(true);
        this.context = context;
        this.parentView = parentView;
       
        this.setScaleType(ScaleType.MATRIX);
        this.setOnTouchListener(imgOnTouchListener);
 }
     
     
     OnTouchListener imgOnTouchListener= new OnTouchListener(){
      
      public boolean onTouch(View v, MotionEvent event) {
      // Handle touch events here...
             switch (event.getAction() & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_DOWN:
                     savedMatrix.set(matrix);
                     start.set(event.getX(), event.getY());
                     //Log.d(TAG, "TouchImage -- mode=DRAG");
                     mode = DRAG;
                     break;
             case MotionEvent.ACTION_POINTER_DOWN:
                     oldDist = spacing(event);
                     //Log.d(TAG, "TouchImage -- oldDist=" + oldDist);
                     if (oldDist > 10f) {
                             savedMatrix.set(matrix);
                             midPoint(mid, event);
                             mode = ZOOM;
                             Log.d(TAG, "TouchImage -- mode=ZOOM");
                     }
                     break;
             case MotionEvent.ACTION_UP:
              //做最後確認
                 getRebuildMatrix();
              mode = NONE;
                 Log.d(TAG, "TouchImage -- mode = NONE");
                 break;
             case MotionEvent.ACTION_POINTER_UP:
             
                 mode = NONE;
                 Log.d(TAG, "TouchImage -- mode = NONE");
                 break;
             case MotionEvent.ACTION_MOVE:
              Matrix _m = new Matrix();
                    if (mode == DRAG) { // && getMatrixScale(matrix) > maxScale
                             // ...
                        float xx = event.getX() - start.x;
                        float yy =event.getY() - start.y;
                        _m.set(savedMatrix);
                        _m.postTranslate(xx, yy);
                       matrix.set(_m);
                    setImageMatrix(matrix);
                            
                     } else if (mode == ZOOM) {
                              float newDist = spacing(event);
                             //Log.d(TAG, "TouchImage -- newDist=" + newDist);
                             if (newDist > 10f) {
                              float scale = newDist / oldDist;
                              
                            _m.set(savedMatrix);
                            _m.postScale(scale, scale, mid.x, mid.y);
                           
                           if (checkScale( _m,false)){
                            matrix.set(_m);
                            setImageMatrix(matrix);
                            }
                             }
                     }
                    
                     break;
             }
             return true;
      }
      
        
     };
            
     public void setImage(Bitmap bm, int displayWidth, int displayHeight) { 
         super.setImageBitmap(bm);
  
         //Fit to screen.
   frameWidth = displayWidth;
         frameHeight = displayHeight;
         
         bitmapWidth = bm.getWidth();
         bitmapHeight = bm.getHeight();
         
         
         savedMatrix.set(matrix);
         matrix.set(savedMatrix);
         float scale = setImageNormalScale(bm.getWidth(),bm.getHeight());
         minScale = scale;
         // Center the image
         setCenterImage();
         
        
  }

  private float setImageNormalScale(int imageWidth, int imageHeight){

         float scale;
         if ((frameHeight / imageHeight) >= (frameWidth / imageWidth)){
                 scale =  (float)frameWidth / (float)imageWidth;
         } else {
                 scale = (float)frameHeight / (float)imageHeight;
         }         
         matrix.postScale(scale, scale, mid.x, mid.y);
         setImageMatrix(matrix);
         
         return scale;
  }
  
  private void setCenterImage(){
   // Center the image
   float redundantYSpace = (float)frameHeight - (minScale * (float)bitmapHeight) ;
         float redundantXSpace = (float)frameWidth - (minScale * (float)bitmapWidth);
         
         redundantYSpace /= (float)2;
         redundantXSpace /= (float)2;        
         
         matrix.postTranslate(redundantXSpace, redundantYSpace);
         setImageMatrix(matrix);
  }
  

     /** Determine the space between the first two fingers */
     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);
     }

     /** Calculate the mid point of the first two fingers */
     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 getRebuildMatrix(){
      //確認大小
      boolean scaleProblem = checkScale(matrix,true);
      if (!scaleProblem){
       //改變大小
       //matrix.postScale(minScale, minScale, mid.x, mid.y);
       matrix.setScale(minScale, minScale);
       setCenterImage();       
      }else{
      //確認邊界
       float[] check = checkBorder(matrix);
          //x1,x2,y1,y2
          Log.v(TAG,"確認誰越界 -- "+ check[0] + "," + check[1] + "," + check[2] + "," + check[3]);
          if (check[0] != 0f){
           matrix.postTranslate(check[0], 0);
           setImageMatrix(matrix);
          }
          if (check[1] != 0f){
           matrix.postTranslate(check[1], 0);
           setImageMatrix(matrix);
          }      
          if (check[2] != 0f){
           matrix.postTranslate(0, check[2]);
           setImageMatrix(matrix);
          }
          if (check[3] != 0f){
           matrix.postTranslate(0, check[3]);
           setImageMatrix(matrix);
          }
      }
     
     
      
     }
     
     private boolean checkScale(Matrix _m, boolean smallcheck){
      float[] f = new float[9];
         _m.getValues(f); 
         // 圖片頂點四座標
         float x1 = f[0] * 0 + f[1] * 0 + f[2];
         float y1 = f[3] * 0 + f[4] * 0 + f[5];
         float x2 = f[0] * bitmapWidth + f[1] * 0 + f[2];
         float y2 = f[3] * bitmapWidth + f[4] * 0 + f[5];
         // 圖片現在寬度
         double width = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
         
         float maxWidth = frameWidth *3;
     // Log.w(TAG," -- -- -- 比較小? " + frameWidth  + " 或比較大?" + maxWidth);
      if (smallcheck){
      if (width < frameWidth) return false;
      }
      if (width > maxWidth)  return false;
              
     return true;
     }
     
     private  float[] checkBorder ( Matrix _m){
      float[] check = {0f,0f,0f,0f};
         float[] f = new float[9];
         _m.getValues(f);
        
         // 圖片頂點四座標
         float x1 = f[0] * 0 + f[1] * 0 + f[2];
         float y1 = f[3] * 0 + f[4] * 0 + f[5];
         float x4 = f[0] * bitmapWidth + f[1] * bitmapHeight + f[2];
         float y4 = f[3] * bitmapWidth + f[4] * bitmapHeight + f[5];
     
         
        // 出界判斷
      Log.i(TAG,"出界判斷 -- frameWidth : " + frameWidth + "  frameHeight  : " + frameHeight);
      Log.v(TAG,"座標判斷2 -- (" + x1 + ", " + y1 + ") , (" + x4 + ", " + y4 + ")");
  
         if (x1 > 0) check[0] = -x1;
         if (x4 < frameWidth)check[1] = frameWidth-x4;
           
         if (y1 > 0) check[2] = -y1;
         Log.w(TAG, "-- " + y4 + " vs " + frameHeight + " ( " + this.getHeight() +" )");
         if (y4 <  frameHeight) check[3] = frameHeight-y4;        
         
         return check;
     }

}

建立TouchImageView物件的時候:

int bitmapMinWidth = 800;

TouchImageView view = new TouchImageView(ctx,null);
Resources res=getResources();  
InputStream is = res.openRawResource(R.drawable.bitmap001);
Bitmap bmp = BitmapFactory.decodeStream(is,null,null);
int bitmapMinHeight = 0;
float s =  bitmapMinWidth/(float)bmp.getWidth();
bitmapMinHeight = (int) (bmp.getHeight() * s); 

view.setImage(bmp,  bitmapMinWidth, bitmapMinHeight);

沒有留言:

張貼留言

歡迎大家留言提問,我會答的都會盡力回答!
如果太久沒出現回應就是我又忘記回來看留言了TAT