Android ImageView 縮放、拖動、旋轉

直接上代碼


    <cn.weijian.sweeping_robot.widget.MatrixImageView
        android:layout_above="@id/robot_bottom_layout"
        android:id="@+id/slamware_map_image_view"
        android:scaleType="matrix"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:src="@drawable/map"/>

package cn.weijian.sweeping_robot.widget;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
//import android.support.v7.widget.AppCompatImageView;
import android.widget.ImageView;
import androidx.annotation.Nullable;

import cn.weijian.sweeping_robot.utils.ViewUtils;

public class MatrixImageView extends ImageView {
    private static final String TAG = MatrixImageView.class.getSimpleName();

    private Matrix currentMatrix = new Matrix();
    private Matrix savedMatrix = new Matrix();

    private PointF startF = new PointF();
    private PointF midF = new PointF();

    private float oldDis = 1f;          // 初始的兩個手指按下的觸摸點的距離
    private float saveRotate = 0F;      // 保存了的角度值

    private static final int MODE_NONE = 0; // 默認的觸摸模式
    private static final int MODE_DRAG = 1; // 拖拽模式
    private static final int MODE_ZOOM = 2; // 縮放模式
    private int mode = MODE_NONE;

    private int ddx=0, ddy=0;
    private float dScale = 1;

    public MatrixImageView(Context context) {
        super(context);
        init();
    }

    public MatrixImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MatrixImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public MatrixImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init(){
        Log.e(TAG, "width: "+getWidth()+", height: "+getHeight());
        setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                return true;
            }
        });
        setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                ImageView view = (ImageView)v;
                switch (event.getAction()& MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:// 單點接觸屏幕時
                        savedMatrix.set(currentMatrix);
                        startF.set(event.getX(), event.getY());
                        mode=MODE_DRAG;
                        break;

                    case MotionEvent.ACTION_POINTER_DOWN:// 第二個手指按下事件
                        oldDis = ViewUtils.calDis(event);
                        if (oldDis > 10F) {
                            savedMatrix.set(currentMatrix);
                            midF = ViewUtils.calMidPoint(event);
                            mode = MODE_ZOOM;
                        }
                        saveRotate = ViewUtils.calRotation(event);//計算初始的角度
                        break;
                    case MotionEvent.ACTION_MOVE:// 觸摸點移動時
                        if (mode == MODE_DRAG) {
                            // 單點觸控拖拽平移
                            float dx = event.getX() - startF.x;
                            float dy = event.getY() - startF.y;
                            startF.set(event.getX(), event.getY());
//                            if(Math.abs(ddx+dx)<=view.getWidth()*dScale && Math.abs(ddy+dy)<=view.getHeight()*dScale)
                            {
                                ddx+=dx;
                                ddy+=dy;
                                currentMatrix.postTranslate(dx, dy);
                            }
                        }
                        else if(mode == MODE_ZOOM && event.getPointerCount() == 2){
                            // 兩點觸控拖放
                            float newDis = ViewUtils.calDis(event);
                            float rotate = ViewUtils.calRotation(event);

                            //指尖移動距離大於10F縮放
                            if (newDis > 10F){
                                float scale = newDis / oldDis;
                                oldDis = newDis;
                                if(scale*dScale<10 && scale*dScale>0.1){
                                    dScale *= scale;
                                    currentMatrix.postScale(scale, scale, midF.x, midF.y);
                                    Log.e(TAG, "dScale: "+dScale+", scale: "+scale);
                                }
                            }

                            //當旋轉的角度大於5F才進行旋轉
                            if(Math.abs(rotate - saveRotate)>1F){
                                currentMatrix.postRotate(rotate - saveRotate, view.getWidth() / 2, view.getHeight() / 2);
                                saveRotate = rotate;
                                Log.e(TAG, "saveRotate: "+saveRotate+", rotate: "+rotate);
                            }
                        }
                        break;

                    case MotionEvent.ACTION_UP:// 單點離開屏幕時
                        mode=MODE_NONE;
                        break;
                    case MotionEvent.ACTION_POINTER_UP:// 第二個點離開屏幕時
                        savedMatrix.set(currentMatrix);
                        if(event.getActionIndex()==0)
                            startF.set(event.getX(1), event.getY(1));
                        else if(event.getActionIndex()==1)
                            startF.set(event.getX(0), event.getY(0));
                        mode=MODE_DRAG;
                        break;
                }
                view.setImageMatrix(currentMatrix);
                return false;
            }
        });
    }

    public Matrix getCurrentMatrix() {
        return currentMatrix;
    }

    public Matrix getSavedMatrix() {
        return savedMatrix;
    }

    public float getSaveRotate() {
        return saveRotate;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章