Android中实现图片平移、缩放、旋转同步进行

来源:互联网 发布:windows照片整理软件 编辑:程序博客网 时间:2024/04/28 03:11

转载请注明转自:noyet12的博客
博客原址:http://blog.csdn.net/u012975705/article/details/49797911
源码下载地址:
(github)https://github.com/noyo/RotateZoomImageView
(csdn)http://download.csdn.net/detail/u012975705/9263323
EventBus2.4.jar下载

前言

之前因为项目需求,其中使用到了图片的单击显示取消,图片平移缩放功能,昨天突然想再加上图片的旋转功能,在网上看了很多相关的例子,可是没看到能同时实现我想要的功能的。
需求:
(1)图片平移、缩放、旋转等一系列操作后,图片需要自动居中显示。
(2)图片旋转后选自动水平显示或者垂直显示
(3)图片在放大缩小的同时都能旋转

Demo实现部分效果截图

这里写图片描述

Demo主要代码

MainActivity.javapackage com.practice.noyet.rotatezoomimageview;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.graphics.PointF;import android.graphics.RectF;import android.os.AsyncTask;import android.os.Bundle;import android.util.DisplayMetrics;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;import com.ypy.eventbus.EventBus;import java.io.File;import java.math.BigDecimal;/** * package: com.practice.noyet.rotatezoomimageview * Created by noyet on 2015/11/11. */public class MainActivity extends Activity implements View.OnTouchListener {    private ImageView mImageView;    private PointF point0 = new PointF();    private PointF pointM = new PointF();    private final int NONE = 0;    /**     * 平移     */    private final int DRAG = 1;    /**     * 旋转、缩放     */    private final int ZOOM = 2;    /**     * 设定事件模式     */    private int mode = NONE;    /**     * 图片缩放矩阵     */    private Matrix matrix = new Matrix();    /**     * 保存触摸前的图片缩放矩阵     */    private Matrix savedMatrix = new Matrix();    /**     * 保存触点移动过程中的图片缩放矩阵     */    private Matrix matrix1 = new Matrix();    /**     * 屏幕高度     */    private int displayHeight;    /**     * 屏幕宽度     */    private int displayWidth;    /**     * 最小缩放比例     */    protected float minScale = 1f;    /**     * 最大缩放比例     */    protected float maxScale = 3f;    /**     * 当前缩放比例     */    protected float currentScale = 1f;    /**     * 多点触摸2个触摸点间的起始距离     */    private float oldDist;    /**     * 多点触摸时图片的起始角度     */    private float oldRotation = 0;    /**     * 旋转角度     */    protected float rotation = 0;    /**     * 图片初始宽度     */    private int imgWidth;    /**     * 图片初始高度     */    private int imgHeight;    /**     * 设置单点触摸退出图片显示时,单点触摸的灵敏度(可针对不同手机单独设置)     */    protected final int MOVE_MAX = 2;    /**     * 单点触摸时手指触发的‘MotionEvent.ACTION_MOVE’次数     */    private int fingerNumMove = 0;    private Bitmap bm;    /**     * 保存matrix缩放比例     */    private float matrixScale= 1;    /*private String imagePath;*/    /**     * 显示被存入缓存中的网络图片     *     * @param event 观察者事件     */    public void onEventMainThread(CustomEventBus event) {        if (event == null) {            return;        }        if (event.type == CustomEventBus.EventType.SHOW_PICTURE) {            bm = (Bitmap) event.obj;            showImage();        }    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initData();    }    public void initData() {        // TODO Auto-generated method stub        bm = BitmapFactory.decodeResource(getResources(), R.drawable.alipay);        DisplayMetrics dm = getResources().getDisplayMetrics();        displayWidth = dm.widthPixels;        displayHeight = dm.heightPixels;        mImageView = (ImageView) findViewById(R.id.image_view);        mImageView.setOnTouchListener(this);        showImage();        //显示网络图片时使用        /*File file = MainApplication.getInstance().getImageCache()                .getDiskCache().get(图片路径);        if (!file.exists()) {            Toast.makeText(this, "图片路径错误", Toast.LENGTH_SHORT).show();        } else {            new MyTask().execute(file);        }*/    }    @Override    public boolean onTouch(View view, MotionEvent event) {        ImageView imageView = (ImageView) view;        switch (event.getAction() & MotionEvent.ACTION_MASK) {            case MotionEvent.ACTION_DOWN:                savedMatrix.set(matrix);                point0.set(event.getX(), event.getY());                mode = DRAG;                System.out.println("MotionEvent--ACTION_DOWN");                break;            case MotionEvent.ACTION_POINTER_DOWN:                oldDist = spacing(event);                oldRotation = rotation(event);                savedMatrix.set(matrix);                setMidPoint(pointM, event);                mode = ZOOM;                System.out.println("MotionEvent--ACTION_POINTER_DOWN---" + oldRotation);                break;            case MotionEvent.ACTION_UP:                if (mode == DRAG && (fingerNumMove <= MOVE_MAX)) {                    MainActivity.this.finish();                }                checkView();                centerAndRotate();                imageView.setImageMatrix(matrix);                System.out.println("MotionEvent--ACTION_UP");                fingerNumMove = 0;                break;            case MotionEvent.ACTION_POINTER_UP:                mode = NONE;                System.out.println("MotionEvent--ACTION_POINTER_UP");                break;            case MotionEvent.ACTION_MOVE:                operateMove(event);                imageView.setImageMatrix(matrix1);                fingerNumMove++;                System.out.println("MotionEvent--ACTION_MOVE");                break;        }        return true;    }    @Override    protected void onDestroy() {        // TODO Auto-generated method stub        super.onDestroy();        if (bm != null && !bm.isRecycled()) {            bm.recycle(); // 回收图片所占的内存            System.gc(); // 提醒系统及时回收        }    }    /**     * 显示图片     */    private void showImage() {        imgWidth = bm.getWidth();        imgHeight = bm.getHeight();        mImageView.setImageBitmap(bm);        matrix.setScale(1, 1);        centerAndRotate();        mImageView.setImageMatrix(matrix);    }    /**     * 触点移动时的操作     *     * @param event 触摸事件     */    private void operateMove(MotionEvent event) {        matrix1.set(savedMatrix);        switch (mode) {            case DRAG:                matrix1.postTranslate(event.getX() - point0.x, event.getY() - point0.y);                break;            case ZOOM:                rotation = rotation(event) - oldRotation;                float newDist = spacing(event);                float scale = newDist / oldDist;                currentScale = (scale > 3.5f) ? 3.5f : scale;                System.out.println("缩放倍数---" + currentScale);                System.out.println("旋转角度---" + rotation);                /** 縮放 */                matrix1.postScale(currentScale, currentScale, pointM.x, pointM.y);                /** 旋轉 */                matrix1.postRotate(rotation, displayWidth / 2, displayHeight / 2);                break;        }    }    /**     * 两个触点的距离     *     * @param event 触摸事件     * @return float     */    private float spacing(MotionEvent event) {        float x = event.getX(0) - event.getX(1);        float y = event.getY(0) - event.getY(1);        return (float) Math.sqrt(x * x + y * y);    }    /**     * 获取旋转角度     */    private float rotation(MotionEvent event) {        double delta_x = (event.getX(0) - event.getX(1));        double delta_y = (event.getY(0) - event.getY(1));        double radians = Math.atan2(delta_y, delta_x);        return (float) Math.toDegrees(radians);    }    /**     * 两个触点的中间坐标     *     * @param pointM 中间坐标     * @param event  触摸事件     */    private void setMidPoint(PointF pointM, MotionEvent event) {        float x = event.getX(0) + event.getY(1);        float y = event.getY(0) + event.getY(1);        pointM.set(x / 2, y / 2);    }    /**     * 检查约束条件(缩放倍数)     */    private void checkView() {        if (currentScale > 1) {            if (currentScale * matrixScale > maxScale) {                matrix.postScale(maxScale / matrixScale, maxScale / matrixScale, pointM.x, pointM.y);                matrixScale = maxScale;            } else {                matrix.postScale(currentScale, currentScale, pointM.x, pointM.y);                matrixScale *= currentScale;            }        } else {            if (currentScale * matrixScale < minScale) {                matrix.postScale(minScale / matrixScale, minScale / matrixScale, pointM.x, pointM.y);                matrixScale = minScale;            } else {                matrix.postScale(currentScale, currentScale, pointM.x, pointM.y);                matrixScale *= currentScale;            }        }    }    /**     * 图片居中显示、判断旋转角度 小于(90 * x + 45)度图片旋转(90 * x)度 大于则旋转(90 * (x+1))     */    private void centerAndRotate() {        RectF rect = new RectF(0, 0, imgWidth, imgHeight);        matrix.mapRect(rect);        float width = rect.width();        float height = rect.height();        float dx = 0;        float dy = 0;        if (width < displayWidth) {            dx = displayWidth / 2 - width / 2 - rect.left;        } else if (rect.left > 0) {            dx = -rect.left;        } else if (rect.right < displayWidth) {            dx = displayWidth - rect.right;        }        if (height < displayHeight) {            dy = displayHeight / 2 - height / 2 - rect.top;        } else if (rect.top > 0) {            dy = -rect.top;        } else if (rect.bottom < displayHeight) {            dy = displayHeight - rect.bottom;        }        matrix.postTranslate(dx, dy);        if (rotation != 0) {            int rotationNum = (int) (rotation / 90);            float rotationAvai = new BigDecimal(rotation % 90).setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();            float realRotation = 0;            if (rotation > 0) {                realRotation = rotationAvai > 45 ? (rotationNum + 1) * 90 : rotationNum * 90;            } else if (rotation < 0) {                realRotation = rotationAvai < -45 ? (rotationNum - 1) * 90 : rotationNum * 90;            }            System.out.println("realRotation: " + realRotation);            matrix.postRotate(realRotation, displayWidth / 2, displayHeight / 2);            rotation = 0;        }    }    /**     * 显示网络图片时使用     */    private class MyTask extends AsyncTask<File, File, Bitmap> {        Bitmap bitmap;        String path;        int scale = 1;        long size;        @Override        protected Bitmap doInBackground(File... params) {            // TODO Auto-generated method stub            try {                size = params[0].length();                path = params[0].getAbsolutePath();                BitmapFactory.Options options = new BitmapFactory.Options();                options.inJustDecodeBounds = true;                BitmapFactory.decodeFile(path, options);                scale = calculateInSampleSize(options, displayWidth,                        displayHeight);                options.inJustDecodeBounds = false;                options.inSampleSize = scale;                bitmap = BitmapFactory.decodeFile(path, options);            } catch (Exception e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            return bitmap;        }        @Override        protected void onPostExecute(Bitmap result) {            // TODO Auto-generated method stub            EventBus.getDefault().post(                    new CustomEventBus(CustomEventBus.EventType.SHOW_PICTURE, result));        }        /**         * 获取图片缩放比例         *         * @param paramOptions Options         * @param paramInt1    宽         * @param paramInt2    高         * @return int         */        private int calculateInSampleSize(BitmapFactory.Options paramOptions,                                          int paramInt1, int paramInt2) {            int i = paramOptions.outHeight;            int j = paramOptions.outWidth;            int k = 1;            if ((i > paramInt2) || (j > paramInt1)) {                int m = Math.round(i / paramInt2);                int n = Math.round(j / paramInt1);                k = m < n ? n : m;            }            return k;        }    }}
CustomEventBus.javapackage com.practice.noyet.rotatezoomimageview;/** * package: com.practice.noyet.rotatezoomimageview * Created by noyet on 2015/11/11. */public class CustomEventBus {    public EventType type;    public Object obj;    public CustomEventBus(EventType type, Object obj) {        this.type = type;        this.obj = obj;    }    enum EventType {        SHOW_PICTURE    }}
2 0
原创粉丝点击