1. 程式人生 > >Android 實現圖片縮放和拖動

Android 實現圖片縮放和拖動

今天我們來編寫一個縮放效果的ImageView ,網上有很多人都講了這些。但有許多人都直接使用了庫檔案,

那麼我們今天做的是直接上程式碼編寫一個拖動和縮放的ImageView,具體看效果圖,
效果圖

那麼簡單了分析一下。在手機上縮放圖片和拖動要用到什麼?手指對不對

那麼控制元件上什麼事件和手機有關。View.OnTouchListener 對不對。

ok,那麼先新建一個Class
···
public class BaseDragZoomImageView extends ImageView implements View.OnTouchListener
···

沒錯,繼承ImageView 並且新增View.OnTouchListener事件

然後我們看看建構函式

    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); }

對,在建構函式中,我們將setOnTouchListener 設定了。
那麼這個setOnTouchListener 具體怎麼做。我們就先分析一下onTouch 中MotionEvent。
我們都知道手指的操作有很多,那麼Andorid自然也將這種情況分了很多種case。
- MotionEvent.ACTION_DOWN 手指按下螢幕
- MotionEvent.ACTION_MOVE 手指在螢幕上移動
- MotionEvent.ACTION_UP 手指離開螢幕
- MotionEvent.ACTION_POINTER_UP 當觸點離開螢幕,但是螢幕上還有觸點(手指)
- MotionEvent.ACTION_POINTER_DOWN 當螢幕上已經有觸點(手指),再有一個觸點壓下螢幕
很顯然,這些看起來好像都能夠用得到。

    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;
            // 手指在螢幕上移動,改事件會被不斷觸發
            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);// 結束距離
                    if (endDis > 10f) { // 兩個手指併攏在一起的時候畫素大於10
                        float scale = endDis / startDis;// 得到縮放倍數
                        matrix.set(currentMatrix);
                        matrix.postScale(scale, scale,midPoint.x,midPoint.y);
                    }
                }
                break;
            // 手指離開螢幕
            case MotionEvent.ACTION_UP:
                // 當觸點離開螢幕,但是螢幕上還有觸點(手指)
            case MotionEvent.ACTION_POINTER_UP:
                mode = 0;
                break;
            // 當螢幕上已經有觸點(手指),再有一個觸點壓下螢幕
            case MotionEvent.ACTION_POINTER_DOWN:
                mode = MODE_ZOOM;
                /** 計算兩個手指間的距離 */
                startDis = distance(event);
                /** 計算兩個手指間的中間點 */
                if (startDis > 10f) { // 兩個手指併攏在一起的時候畫素大於10
                    midPoint = mid(event);
                    //記錄當前ImageView的縮放倍數
                    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;// 初始狀態
    /** 拖拉照片模式 */
    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;
            // 手指在螢幕上移動,改事件會被不斷觸發
            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);// 結束距離
                    if (endDis > 10f) { // 兩個手指併攏在一起的時候畫素大於10
                        float scale = endDis / startDis;// 得到縮放倍數
                        matrix.set(currentMatrix);
                        matrix.postScale(scale, scale,midPoint.x,midPoint.y);
                    }
                }
                break;
            // 手指離開螢幕
            case MotionEvent.ACTION_UP:
                // 當觸點離開螢幕,但是螢幕上還有觸點(手指)
            case MotionEvent.ACTION_POINTER_UP:
                mode = 0;
                break;
            // 當螢幕上已經有觸點(手指),再有一個觸點壓下螢幕
            case MotionEvent.ACTION_POINTER_DOWN:
                mode = MODE_ZOOM;
                /** 計算兩個手指間的距離 */
                startDis = distance(event);
                /** 計算兩個手指間的中間點 */
                if (startDis > 10f) { // 兩個手指併攏在一起的時候畫素大於10
                    midPoint = mid(event);
                    //記錄當前ImageView的縮放倍數
                    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>

就是這麼簡單。

相關推薦

Android 實現圖片

今天我們來編寫一個縮放效果的ImageView ,網上有很多人都講了這些。但有許多人都直接使用了庫檔案, 那麼我們今天做的是直接上程式碼編寫一個拖動和縮放的ImageView,具體看效果圖, 那麼簡單了分析一下。在手機上縮放圖片和拖動要用到什麼?手指對不

Android自定義imageview可對圖片進行多點

package com.msstudent.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import andro

【EasyAR學習】模型

        開發AR手機端軟體時,雙手縮放、拖動模型是最常見的功能,也是一種最基本的互動手段。        在 Unity 中想要獲取使用者的鍵盤或滑鼠的事件的話,就必須使用 Input 類來獲取。一般來說 Input 類的方法需要寫在 Update() 方法中。   

android實現圖片、移動、單擊退出、雙擊

實現思路 思路:重寫用於顯示圖片的ImageView,定義ScaleGestureDetector(縮放手勢檢測)型別、GestureDetector(雙擊手勢檢測)型別的變數進行手勢檢測並重寫方法實現圖片的縮放、移動、單擊退出、雙擊放大等功能。 重

surfaceView實現圖片功能

還是老闆牛,多向他學習請教。之前折騰了好一會兒的問題,被老闆一上午搞定。 問題:採用surface來實現多點觸控縮放,拖動顯示功能。 附上初稿程式碼,明天再好好整理下, public class MySurfaceView3 extends SurfaceView impl

C#實現圖片(包括旋轉)

using System; using System.Collections; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Web; using Syst

flutter實現拽雙擊放大的圖片功能

flutter實現可縮放可拖拽雙擊放大的圖片功能 可縮放可拖拽的功能,可實現圖片或者其他widget的縮放已經拖拽並支援雙擊放大的功能 我們知道官方提供了雙擊縮放,但是不支援拖拽的功能,我們要實現向百度地圖那樣可以縮放又可以拖拽的功能,官方的方法就不支援了。下面先演示下功能: 引數只有兩個:1、child

使用Opencv實現圖片

方法一: 實現步驟   1. load 載入圖片     2. info    讀取圖片資訊       3. resize   設定寬高   

點選螢幕對顯示物件進行操作:調整位置/旋轉模式/

1.載入資源 2.將資源新增到顯示列表並設定錨點 ////////////////////////////////*調整位置關鍵程式碼*/ this.stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, (e: egret.TouchEvent) =&

php實現圖片,超詳細註釋

<?php //header("content-type:image/png"); * @todo 把一張圖片按照使用者定義的高寬進行縮放,並把處理後的圖片重新命名,放在指定資料夾 * @param string $width:使用者定義的需要處理成的目標寬度 * @param string

js滑鼠滾輪事件詳解(全相容ie、chrome、firefox)實現圖片

以前看到的都是用IE的zoom,所以非IE就不支援,昨天看到這個js中滑鼠滾輪事件詳解,於是完全相容(IE6-8,FF,Chrome,Opera,Safari)的滑鼠滾軸縮放圖片效果今天就誕生了 ====程式碼如下: var zooming=function(e){  e=window.event

研究中完美顯示K線圖:、多圖MACD疊加

原文請看:https://www.joinquant.com/post/13121?tag=algorithm 2018年11月30日更新: 修正了MACD線不顯示的問題。 以下是原文: 想展現資料,圖無疑是最好的方式。展示股票資料,當然是K線圖了,之前論內有人用matplotlib

RecyclerView 實現側滑刪除排序

在使用ListView的時候實現拖動排序,主要靠繼承別人第三方的,在網上有很多例子, 這裡不介紹,主要是介紹一下recycleview的拖動排序和滑動刪除 一、主要知識點:             1、 ItemTouchHelper.Callback的使用        

關於百度地圖拽的回撥函式

1.縮放的回撥函式 zoomstart {type, target} 地圖更改縮放級別開始時觸發觸發此事件 zoomend {type, target} 地圖更改縮放級別結束時觸發觸發此事件   a、實現縮放動作開始時,返回地圖中心點座標: map

OpenCV實現圖片

import cv2 img = cv2.imread('./res/aero3.jpg') print(img.shape[:2]) height, width = img.shape[:2] reSize1 = cv2.resize(img, (2*

fresco如何配合PhotoView使用實現圖片

這裡有兩種方法: 第一種:修改photoview https://github.com/ongakuer/PhotoDraweeView 第二種:繼承photoview,自定義DraweeView https://github.com/biezhihua/MySimpleD

IOS下,利用捏合手勢實現影象顯示

影象的縮放檢視,在移動終端上早已不是問題,任何一個人都能夠熟練的操作影象的縮放。本文所講述的重點並不是應用層面上的,而是從編碼的角度去自己實現一個影象的縮放應用。作者(就是我自己)最近在做一款APP,其中有一個功能就是抓取PC桌面的影象傳送到手機上顯示。雖說現在的手機螢幕

Glide 入門到精通之四——圖片調整大小

圖片調整大小和縮放是有趣的,在實際應用中也是很重要的 用 resize(x,y) 調整圖片大小 通常情況下,如果你的伺服器或者 API 提供的影象是你需要的精確尺寸,這時是完美的情況下,在記憶體小號和影象質量之間的權衡。 在和 Picasso 比較

C#圖片處理之:圖片剪裁

應聽眾點播要求,今天說說用C#做圖片的縮放和剪裁,相信很多人會對這部分內容感興趣,畢竟這個操作太實用了。 其實在GDI+中,縮放和剪裁可以看作同一個操作,無非就是原始區域的選擇不同罷了。空口無憑,先看具體演算法可能更好理解。         /// <summary&g

Android Bitmap圖片優化,用canvas替代Matrix進行,解決一些錯我

前面用Matrix來縮放Bitmap,發現有些情況下會丟擲錯誤,導致圖片空白。 /** * 縮放 * * @param bm * @param newWidth * @param newHeight *