Android實現(xiàn)ImageView圖片縮放和拖動
今天我們來編寫一個縮放效果的ImageView ,網(wǎng)上有很多人都講了這些。但有許多人都直接使用了庫文件,
那么我們今天做的是直接上代碼編寫一個拖動和縮放的ImageView,具體看效果圖
那么簡單了分析一下。在手機上縮放圖片和拖動要用到什么?手指對不對
那么控件上什么事件和手機有關(guān)。View.OnTouchListener 對不對。
ok,那么先新建一個Class
···
public class BaseDragZoomImageView extends ImageView implements View.OnTouchListener
···
沒錯,繼承ImageView 并且添加View.OnTouchListener事件
然后我們看看構(gòu)造函數(shù)
public BaseDragZoomImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setOnTouchListener(this); } public BaseDragZoomImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); setOnTouchListener(this); } public BaseDragZoomImageView(Context context) { this(context, null); setOnTouchListener(this); }
對,在構(gòu)造函數(shù)中,我們將setOnTouchListener 設置了。
那么這個setOnTouchListener 具體怎么做。我們就先分析一下onTouch 中MotionEvent。
我們都知道手指的操作有很多,那么Andorid自然也將這種情況分了很多種case。
- MotionEvent.ACTION_DOWN 手指按下屏幕
- MotionEvent.ACTION_MOVE 手指在屏幕上移動
- MotionEvent.ACTION_UP 手指離開屏幕
- MotionEvent.ACTION_POINTER_UP 當觸點離開屏幕,但是屏幕上還有觸點(手指)
- MotionEvent.ACTION_POINTER_DOWN 當屏幕上已經(jīng)有觸點(手指),再有一個觸點壓下屏幕
很顯然,這些看起來好像都能夠用得到。
public boolean onTouch(View v, MotionEvent event) { /** 通過與運算保留最后八位 MotionEvent.ACTION_MASK = 255 */ switch (event.getAction() & MotionEvent.ACTION_MASK) { // 手指壓下屏幕 case MotionEvent.ACTION_DOWN: mode = MODE_DRAG; // 記錄ImageView當前的移動位置 currentMatrix.set(getImageMatrix()); startPoint.set(event.getX(), event.getY()); break; // 手指在屏幕上移動,改事件會被不斷觸發(fā) case MotionEvent.ACTION_MOVE: // 拖拉圖片 if (mode == MODE_DRAG) { float dx = event.getX() - startPoint.x; // 得到x軸的移動距離 float dy = event.getY() - startPoint.y; // 得到x軸的移動距離 // 在沒有移動之前的位置上進行移動 matrix.set(currentMatrix); matrix.postTranslate(dx, dy); } // 放大縮小圖片 else if (mode == MODE_ZOOM) { float endDis = distance(event);// 結(jié)束距離 if (endDis > 10f) { // 兩個手指并攏在一起的時候像素大于10 float scale = endDis / startDis;// 得到縮放倍數(shù) matrix.set(currentMatrix); matrix.postScale(scale, scale,midPoint.x,midPoint.y); } } break; // 手指離開屏幕 case MotionEvent.ACTION_UP: // 當觸點離開屏幕,但是屏幕上還有觸點(手指) case MotionEvent.ACTION_POINTER_UP: mode = 0; break; // 當屏幕上已經(jīng)有觸點(手指),再有一個觸點壓下屏幕 case MotionEvent.ACTION_POINTER_DOWN: mode = MODE_ZOOM; /** 計算兩個手指間的距離 */ startDis = distance(event); /** 計算兩個手指間的中間點 */ if (startDis > 10f) { // 兩個手指并攏在一起的時候像素大于10 midPoint = mid(event); //記錄當前ImageView的縮放倍數(shù) currentMatrix.set(getImageMatrix()); } break; } setImageMatrix(matrix); return true; }
ok,收工。具體就只有這么多。我們來看下整個class
package com.jonkming.easyui.image.dragzoom.ui; import android.content.Context; import android.graphics.Matrix; import android.graphics.PointF; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; import android.util.FloatMath; /** * 圖片縮放和拖動類 * @Title: BaseDragZoomImageView.java * @Package com.jonkming.easyui.image.dragzoom.ui * @author HuangMingming * @date 2016/11/7 17:40 * @version V1.0 */ public class BaseDragZoomImageView extends ImageView implements View.OnTouchListener{ /** 記錄是拖拉照片模式還是放大縮小照片模式 */ private int mode = 0;// 初始狀態(tài) /** 拖拉照片模式 */ private static final int MODE_DRAG = 1; /** 放大縮小照片模式 */ private static final int MODE_ZOOM = 2; /** 用于記錄開始時候的坐標位置 */ private PointF startPoint = new PointF(); /** 用于記錄拖拉圖片移動的坐標位置 */ private Matrix matrix = new Matrix(); /** 用于記錄圖片要進行拖拉時候的坐標位置 */ private Matrix currentMatrix = new Matrix(); /** 兩個手指的開始距離 */ private float startDis; /** 兩個手指的中間點 */ private PointF midPoint; public BaseDragZoomImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setOnTouchListener(this); } public BaseDragZoomImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); setOnTouchListener(this); } public BaseDragZoomImageView(Context context) { this(context, null); setOnTouchListener(this); } @Override public boolean onTouch(View v, MotionEvent event) { /** 通過與運算保留最后八位 MotionEvent.ACTION_MASK = 255 */ switch (event.getAction() & MotionEvent.ACTION_MASK) { // 手指壓下屏幕 case MotionEvent.ACTION_DOWN: mode = MODE_DRAG; // 記錄ImageView當前的移動位置 currentMatrix.set(getImageMatrix()); startPoint.set(event.getX(), event.getY()); break; // 手指在屏幕上移動,改事件會被不斷觸發(fā) case MotionEvent.ACTION_MOVE: // 拖拉圖片 if (mode == MODE_DRAG) { float dx = event.getX() - startPoint.x; // 得到x軸的移動距離 float dy = event.getY() - startPoint.y; // 得到x軸的移動距離 // 在沒有移動之前的位置上進行移動 matrix.set(currentMatrix); matrix.postTranslate(dx, dy); } // 放大縮小圖片 else if (mode == MODE_ZOOM) { float endDis = distance(event);// 結(jié)束距離 if (endDis > 10f) { // 兩個手指并攏在一起的時候像素大于10 float scale = endDis / startDis;// 得到縮放倍數(shù) matrix.set(currentMatrix); matrix.postScale(scale, scale,midPoint.x,midPoint.y); } } break; // 手指離開屏幕 case MotionEvent.ACTION_UP: // 當觸點離開屏幕,但是屏幕上還有觸點(手指) case MotionEvent.ACTION_POINTER_UP: mode = 0; break; // 當屏幕上已經(jīng)有觸點(手指),再有一個觸點壓下屏幕 case MotionEvent.ACTION_POINTER_DOWN: mode = MODE_ZOOM; /** 計算兩個手指間的距離 */ startDis = distance(event); /** 計算兩個手指間的中間點 */ if (startDis > 10f) { // 兩個手指并攏在一起的時候像素大于10 midPoint = mid(event); //記錄當前ImageView的縮放倍數(shù) currentMatrix.set(getImageMatrix()); } break; } setImageMatrix(matrix); return true; } /** 計算兩個手指間的距離 */ private float distance(MotionEvent event) { float dx = event.getX(1) - event.getX(0); float dy = event.getY(1) - event.getY(0); /** 使用勾股定理返回兩點之間的距離 */ return (float) Math.sqrt(dx * dx + dy * dy); } /** 計算兩個手指間的中間點 */ private PointF mid(MotionEvent event) { float midX = (event.getX(1) + event.getX(0)) / 2; float midY = (event.getY(1) + event.getY(0)) / 2; return new PointF(midX, midY); } }
然后看布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.jonkming.easyui.image.dragzoom.ui.BaseDragZoomImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/dragandzoombase" android:scaleType="matrix" /> </LinearLayout>
就是這么簡單。
代碼所在位置: GitHub
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- android 添加隨意拖動的桌面懸浮窗口
- Android 可拖動的seekbar自定義進度值
- Android 仿淘寶、京東商品詳情頁向上拖動查看圖文詳情控件DEMO詳解
- android 應用內(nèi)部懸浮可拖動按鈕簡單實現(xiàn)代碼
- android Matrix實現(xiàn)圖片隨意放大縮小或拖動
- Android 實現(xiàn)可任意拖動的懸浮窗功能(類似懸浮球)
- Android實現(xiàn)跟隨手指拖動并自動貼邊的View樣式(實例demo)
- Android編程之控件可拖動的實現(xiàn)方法
- Android自定義垂直拖動seekbar進度條
- Android自定義View實現(xiàn)拖動自動吸邊效果
相關(guān)文章
Android Studio修改Log信息顏色的實現(xiàn)
這篇文章主要介紹了Android Studio修改Log信息顏色的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04Android中使用Kotlin實現(xiàn)一個簡單的登錄界面
Kotlin 是一種在 Java 虛擬機上運行的靜態(tài)類型編程語言,被稱之為 Android 世界的Swift,由 JetBrains 設計開發(fā)并開源。接下來本文通過實例代碼給大家講解Android中使用Kotlin實現(xiàn)一個簡單的登錄界面,一起看看吧2017-09-09解決EditText、ListView以及GridView同時使用,輸入法自動跳出來的方法
本篇文章是對在Android中EditText、ListView以及GridView同時使用,輸入法自動跳出來的解決方法進行了詳細的分析介紹,需要的朋友參考下2013-05-05Android App開發(fā)中將View或Drawable轉(zhuǎn)為Bitmap的方法
這篇文章主要介紹了Android App開發(fā)中將View或Drawable轉(zhuǎn)為Bitmap的方法,其中View轉(zhuǎn)換時作者特別提到了getDrawingCache=null問題的解決方法,需要的朋友可以參考下2016-03-03Android開發(fā)RecyclerView實現(xiàn)折線圖效果
這篇文章主要為大家詳細介紹了Android開發(fā)RecyclerView實現(xiàn)折線圖效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-09-09android自定義控件和自定義回調(diào)函數(shù)步驟示例
這篇文章主要介紹了android自定義控件步驟示例,包括為View類增加屬性、響應用戶消息、自定義回調(diào)函數(shù)等方法2014-01-01