多点触控缩放图片及单点触控图片移动

原始图片:


点击放大按钮,或两手拖拉屏幕。


上代码:

[java]  view plain copy print ?
  1. <span style="font-size:13px;"></span><pre name="code" class="java">public class main extends Activity  
  2. {  
  3.     /** Called when the activity is first created. */  
  4.     private ImageZoomView mZoomView;  
  5.     private ZoomState mZoomState;  
  6.     private Bitmap mBitmap;  
  7.     private SimpleZoomListener mZoomListener;  
  8.     private ProgressBar progressBar;  
  9.     private Handler handler = new Handler()  
  10.     {  
  11.         @Override  
  12.         public void handleMessage(Message msg)  
  13.         {  
  14.             progressBar.setVisibility(View.GONE);  
  15.             mZoomView.setImage(mBitmap);  
  16.             mZoomState = new ZoomState();  
  17.             mZoomView.setZoomState(mZoomState);  
  18.             mZoomListener = new SimpleZoomListener();  
  19.             mZoomListener.setZoomState(mZoomState);  
  20.             mZoomView.setOnTouchListener(mZoomListener);  
  21.             resetZoomState();  
  22.         }  
  23.     };  
  24.   
  25.     @Override  
  26.     public void onCreate(Bundle savedInstanceState)  
  27.     {  
  28.         super.onCreate(savedInstanceState);  
  29.           
  30.         // 隐藏顶部程序名称 写在setContentView(R.layout.xxxx);之前,不然报错  
  31.         requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);          
  32.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  33.           
  34.         // 隐藏状态栏  
  35.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  36.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  37.           
  38.         setContentView(R.layout.activity_image);  
  39.         mZoomView = (ImageZoomView) findViewById(R.id.zoomView);  
  40.         progressBar = (ProgressBar) findViewById(R.id.progress_large);  
  41.         progressBar.setVisibility(View.VISIBLE);  
  42.           
  43.           
  44.           
  45.         Thread thread = new Thread(new Runnable()  
  46.         {  
  47.             @Override  
  48.             public void run()  
  49.             {  
  50.                 /* 
  51.                  * 加载网络图片 load form url 
  52.                  */  
  53.                 // mBitmap =  
  54.                 // ImageDownloader.getInstance().getBitmap(url);  
  55.                 mBitmap = BitmapFactory.decodeResource(  
  56.                         main.this.getResources(), R.drawable.test);  
  57.                 handler.sendEmptyMessage(0);  
  58.             }  
  59.         });  
  60.         thread.start();  
  61.   
  62.         ZoomControls zoomCtrl = (ZoomControls) findViewById(R.id.zoomCtrl);  
  63.         zoomCtrl.setOnZoomInClickListener(new OnClickListener()  
  64.         {  
  65.             @Override  
  66.             public void onClick(View v)  
  67.             {  
  68.                 float z = mZoomState.getZoom() + 0.25f;  
  69.                 mZoomState.setZoom(z);  
  70.                 mZoomState.notifyObservers();  
  71.             }  
  72.         });  
  73.         zoomCtrl.setOnZoomOutClickListener(new OnClickListener()  
  74.         {  
  75.   
  76.             @Override  
  77.             public void onClick(View v)  
  78.             {  
  79.                 float z = mZoomState.getZoom() - 0.25f;  
  80.                 mZoomState.setZoom(z);  
  81.                 mZoomState.notifyObservers();  
  82.             }  
  83.         });  
  84.     }  
  85.   
  86.     @Override  
  87.     protected void onDestroy()  
  88.     {  
  89.         super.onDestroy();  
  90.         if (mBitmap != null)  
  91.             mBitmap.recycle();  
  92.   
  93.     }  
  94.   
  95.     private void resetZoomState()  
  96.     {  
  97.         mZoomState.setPanX(0.5f);  
  98.         mZoomState.setPanY(0.5f);  
  99.         mZoomState.setZoom(1f);  
  100.         mZoomState.notifyObservers();  
  101.     }  
  102. }</pre><br>  
  103. <pre name="code" class="java">public class ImageZoomView extends View implements Observer  
  104. {  
  105.   
  106.     private final Paint mPaint =  new Paint(Paint.FILTER_BITMAP_FLAG);  
  107.     private final Rect mRectSrc = new Rect();  
  108.     private final Rect mRectDst = new Rect();  
  109.     private float mAspectQuotient;  
  110.   
  111.     private Bitmap mBitmap;  
  112.     private ZoomState mState;  
  113.   
  114.     public ImageZoomView(Context context, AttributeSet attrs)  
  115.     {  
  116.         super(context, attrs);  
  117.     }  
  118.   
  119.     public void setZoomState(ZoomState state)  
  120.     {  
  121.         if (mState != null)  
  122.         {  
  123.             mState.deleteObserver(this);  
  124.         }  
  125.         mState = state;  
  126.         mState.addObserver(this);  
  127.         invalidate();  
  128.     }  
  129.   
  130.     protected void onDraw(Canvas canvas)  
  131.     {  
  132.         if (mBitmap != null && mState != null)  
  133.         {  
  134.             final int viewWidth = getWidth();  
  135.             final int viewHeight = getHeight();  
  136.             final int bitmapWidth = mBitmap.getWidth();  
  137.             final int bitmapHeight = mBitmap.getHeight();  
  138.   
  139.             final float panX = mState.getPanX();  
  140.             final float panY = mState.getPanY();  
  141.             final float zoomX = mState.getZoomX(mAspectQuotient) * viewWidth  
  142.                     / bitmapWidth;  
  143.             final float zoomY = mState.getZoomY(mAspectQuotient) * viewHeight  
  144.                     / bitmapHeight;  
  145.   
  146.             // Setup source and destination rectangles  
  147.             mRectSrc.left = (int) (panX * bitmapWidth - viewWidth / (zoomX * 2));  
  148.             mRectSrc.top = (int) (panY * bitmapHeight - viewHeight  
  149.                     / (zoomY * 2));  
  150.             mRectSrc.right = (int) (mRectSrc.left + viewWidth / zoomX);  
  151.             mRectSrc.bottom = (int) (mRectSrc.top + viewHeight / zoomY);  
  152.             mRectDst.left = getLeft();  
  153.             mRectDst.top = getTop();  
  154.             mRectDst.right = getRight();  
  155.             mRectDst.bottom = getBottom();  
  156.   
  157.             // Adjust source rectangle so that it fits within the source image.  
  158.             if (mRectSrc.left < 0)  
  159.             {  
  160.                 mRectDst.left += -mRectSrc.left * zoomX;  
  161.                 mRectSrc.left = 0;  
  162.             }  
  163.             if (mRectSrc.right > bitmapWidth)  
  164.             {  
  165.                 mRectDst.right -= (mRectSrc.right - bitmapWidth) * zoomX;  
  166.                 mRectSrc.right = bitmapWidth;  
  167.             }  
  168.             if (mRectSrc.top < 0)  
  169.             {  
  170.                 mRectDst.top += -mRectSrc.top * zoomY;  
  171.                 mRectSrc.top = 0;  
  172.             }  
  173.             if (mRectSrc.bottom > bitmapHeight)  
  174.             {  
  175.                 mRectDst.bottom -= (mRectSrc.bottom - bitmapHeight) * zoomY;  
  176.                 mRectSrc.bottom = bitmapHeight;  
  177.             }  
  178.   
  179.             canvas.drawBitmap(mBitmap, mRectSrc, mRectDst, mPaint);  
  180.         }  
  181.     }  
  182.   
  183.     public void update(Observable observable, Object data)  
  184.     {  
  185.         invalidate();  
  186.     }  
  187.   
  188.     private void calculateAspectQuotient()  
  189.     {  
  190.         if (mBitmap != null)  
  191.         {  
  192.             mAspectQuotient = (((float) mBitmap.getWidth()) / mBitmap  
  193.                     .getHeight())  
  194.                     / (((float) getWidth()) / getHeight());  
  195.         }  
  196.     }  
  197.   
  198.     public void setImage(Bitmap bitmap)  
  199.     {  
  200.         mBitmap = bitmap;  
  201.         calculateAspectQuotient();  
  202.         invalidate();  
  203.     }  
  204.   
  205.     @Override  
  206.     protected void onLayout(boolean changed, int left, int top, int right,  
  207.             int bottom)  
  208.     {  
  209.         super.onLayout(changed, left, top, right, bottom);  
  210.         calculateAspectQuotient();  
  211.     }  
  212.   
  213. }  
  214. </pre><br>  
  215. <pre name="code" class="java">public class SimpleZoomListener implements View.OnTouchListener  
  216. {  
  217.   
  218.     public enum ControlType  
  219.     {  
  220.         PAN, ZOOM  
  221.     }  
  222.   
  223.     @SuppressWarnings("unused")  
  224.     private ControlType mControlType = ControlType.PAN;  
  225.   
  226.     private ZoomState mState;  
  227.   
  228.     private float mX;  
  229.     private float mY;  
  230.     private float mGap;  
  231.   
  232.     public void setZoomState(ZoomState state)  
  233.     {  
  234.         mState = state;  
  235.     }  
  236.   
  237.     public void setControlType(ControlType controlType)  
  238.     {  
  239.         mControlType = controlType;  
  240.     }  
  241.       
  242.     public boolean onTouch(View v, MotionEvent event)  
  243.     {  
  244.         final int action = event.getAction();  
  245.         int pointCount = event.getPointerCount();  
  246.         if (pointCount == 1)  
  247.         {  
  248.             final float x = event.getX();  
  249.             final float y = event.getY();  
  250.             switch (action)  
  251.             {  
  252.             case MotionEvent.ACTION_DOWN:  
  253.                 mX = x;  
  254.                 mY = y;  
  255.                 break;  
  256.             case MotionEvent.ACTION_MOVE:  
  257.             {  
  258.                 final float dx = (x - mX) / v.getWidth();  
  259.                 final float dy = (y - mY) / v.getHeight();  
  260.                 mState.setPanX(mState.getPanX() - dx);  
  261.                 mState.setPanY(mState.getPanY() - dy);  
  262.                 mState.notifyObservers();  
  263.                 mX = x;  
  264.                 mY = y;  
  265.                 break;  
  266.             }  
  267.             }  
  268.         }  
  269.         if (pointCount == 2)  
  270.         {  
  271.             final float x0 = event.getX(event.getPointerId(0));  
  272.             final float y0 = event.getY(event.getPointerId(0));  
  273.   
  274.             final float x1 = event.getX(event.getPointerId(1));  
  275.             final float y1 = event.getY(event.getPointerId(1));  
  276.   
  277.             final float gap = getGap(x0, x1, y0, y1);  
  278.             switch (action)  
  279.             {  
  280.             case MotionEvent.ACTION_POINTER_2_DOWN:  
  281.             case MotionEvent.ACTION_POINTER_1_DOWN:  
  282.                 mGap = gap;  
  283.                 break;  
  284.             case MotionEvent.ACTION_POINTER_1_UP:  
  285.                 mX = x1;  
  286.                 mY = y1;  
  287.                 break;  
  288.             case MotionEvent.ACTION_POINTER_2_UP:  
  289.                 mX = x0;  
  290.                 mY = y0;  
  291.                 break;  
  292.             case MotionEvent.ACTION_MOVE:  
  293.             {  
  294.                 final float dgap = (gap - mGap) / mGap;  
  295.                 // Log.d("Gap", String.valueOf(dgap));  
  296.                 Log.d("Gap", String.valueOf((float) Math.pow(20, dgap)));  
  297.                 mState.setZoom(mState.getZoom() * (float) Math.pow(5, dgap));  
  298.                 mState.notifyObservers();  
  299.                 mGap = gap;  
  300.                 break;  
  301.             }  
  302.             }  
  303.         }  
  304.   
  305.         return true;  
  306.     }  
  307.   
  308.     private float getGap(float x0, float x1, float y0, float y1)  
  309.     {  
  310.         return (float) Math.pow(  
  311.                 Math.pow((x0 - x1), 2) + Math.pow((y0 - y1), 2), 0.5);  
  312.     }  
  313.   
  314. }</pre><br>  
  315. <pre name="code" class="java">public class ZoomState extends Observable  
  316. {  
  317.   
  318.     private float mZoom;  
  319.     private float mPanX;  
  320.     private float mPanY;  
  321.   
  322.     public float getPanX()  
  323.     {  
  324.         return mPanX;  
  325.     }  
  326.   
  327.     public float getPanY()  
  328.     {  
  329.         return mPanY;  
  330.     }  
  331.   
  332.     public float getZoom()  
  333.     {  
  334.         return mZoom;  
  335.     }  
  336.   
  337.     public void setPanX(float panX)  
  338.     {  
  339.         if (panX != mPanX)  
  340.         {  
  341.             mPanX = panX;  
  342.             setChanged();  
  343.         }  
  344.     }  
  345.   
  346.     public void setPanY(float panY)  
  347.     {  
  348.         if (panY != mPanY)  
  349.         {  
  350.             mPanY = panY;  
  351.             setChanged();  
  352.         }  
  353.     }  
  354.   
  355.     public void setZoom(float zoom)  
  356.     {  
  357.         if (zoom != mZoom)  
  358.         {  
  359.             mZoom = zoom;  
  360.             setChanged();  
  361.         }  
  362.     }  
  363.   
  364.     public float getZoomX(float aspectQuotient)  
  365.     {  
  366.         return Math.min(mZoom, mZoom * aspectQuotient);  
  367.     }  
  368.   
  369.     public float getZoomY(float aspectQuotient)  
  370.     {  
  371.         return Math.min(mZoom, mZoom / aspectQuotient);  
  372.     }  
  373. }</pre><br>  
  374. <pre name="code" class="java"><?xml version="1.0" encoding="utf-8"?>  
  375. <LinearLayout  
  376.   xmlns:android="http://schemas.android.com/apk/res/android"  
  377.   android:layout_width="wrap_content"  
  378.   android:layout_height="wrap_content"  
  379.   android:orientation="vertical">  
  380.     
  381.    <RelativeLayout  
  382.   
  383.           android:layout_width="fill_parent"  
  384.           android:layout_height="fill_parent">  
  385.             
  386.       <RelativeLayout  
  387.           android:id="@+id/zoomViewRelativeLayout"  
  388.           android:layout_width="fill_parent"  
  389.           android:layout_height="wrap_content"  
  390.           android:layout_above="@+id/zoomControlRelativeLayout"  
  391.           android:layout_marginBottom="2px"  
  392.           >  
  393.             
  394.           <whu.iss.activity.ImageZoomView  
  395.             android:id="@+id/zoomView"  
  396.             android:layout_width="fill_parent"   
  397.             android:layout_height="fill_parent"  
  398.              
  399.             >  
  400.           </whu.iss.activity.ImageZoomView>  
  401.             
  402.          <ProgressBar   
  403.                 android:id="@+id/progress_large"  
  404.                 android:layout_height="wrap_content"  
  405.                 android:layout_width="wrap_content"  
  406.                 style="?android:attr/progressBarStyleLarge"  
  407.                 android:visibility="gone"  
  408.                 android:layout_centerInParent="true"/>  
  409.                   
  410.                
  411.       </RelativeLayout>  
  412.         
  413.        <RelativeLayout  
  414.           android:id="@+id/zoomControlRelativeLayout"  
  415.           android:layout_width="fill_parent"  
  416.           android:layout_height="50px"  
  417.           android:layout_alignParentBottom="true"  
  418.           >  
  419.             
  420.             
  421.             
  422.            <ZoomControls  
  423.                   android:id="@+id/zoomCtrl"  
  424.                   android:layout_width="fill_parent"  
  425.                   android:layout_height="fill_parent"  
  426.   
  427.                   android:layout_centerHorizontal="true"  
  428.                   android:layout_centerVertical="true"  
  429.               
  430.                   android:gravity="center"  
  431.                     
  432.                   >  
  433.               </ZoomControls>  
  434.             
  435.             
  436.         </RelativeLayout>  
  437.        </RelativeLayout>  
  438. </LinearLayout></pre><br>  
  439. 工程下载地址:<a href="http://download.csdn.net/detail/yf210yf/4102077">点击打开链接</a> 另补充 Android Gallery3D 源码 已编译 :地址<a href="http://download.csdn.net/detail/yf210yf/4102113">http://download.csdn.net/detail/yf210yf/4102113</a><span style="white-space:pre; background-color:rgb(240,240,240)"></span><pre name="code" class="java"></pre>  
  440. <pre></pre>  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值