我是靠谱客的博主 无心月饼,最近开发中收集的这篇文章主要介绍Android ZoomImageView手势缩放拖动图片,并将Glide加载的网络图片保存到本地。,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

         在正式写干货时,先说几句题外话。本人今年毕业于一个非常普通的学校的软件工程。之前在学校断断续续的学习了Android开发。大三实习了一年。然后到现在进行Android开发也已经一年多了。一直觉得到网上写博客的人很牛逼,很高大上。之前因为自己实力不行,写作表达能力也不怎么样。一直压抑着写博客的想法。但现在实在是控制不住体内的洪荒之力,打算写写东西。这篇文章是我的第一篇文章,写的不好之处请多多包涵。 

         在当前的项目中有个需求是获取网络上的图片,然后点击图片可以跳转到另一个页面可以自由放大缩小图片,点击图片弹出对话框可以选择保存。知道这个需求后,我抱着不能重复造轮子的心态,第一想法就是百度。果然找到了能用的代码。

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver;
import android.widget.ImageView;

import java.util.ArrayList;
import java.util.List;


/**
 * 可根据点击/多指触控 放大,放小的ImageVIew
 *
 * @author Gloomy
 * @date 2016年07月02日15:12:20
 */
public class ZoomImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener
        , View.OnTouchListener, ScaleGestureDetector.OnScaleGestureListener {

    private static final String TAG = "ZoomImageView";
    private boolean isInit;


    /**
     * 缩放工具
     */
    private Matrix mMatrix;

    /**
     * 缩放的最小值
     */
    private float mMinScale;
    /**
     * 缩放的中间值
     */
    private float mMidScale;
    /**
     * 缩放的最大值
     */
    private float mMaxScale;

    /**
     * 多点手势触 控缩放比率分析器
     */
    private ScaleGestureDetector mScaleGestureDetector;

    //--自由移动

    /**
     * 记录上一次多点触控的数量
     */
    private int mLastPointereCount;

    private float mLastX;
    private float mLastY;
    private int mTouchSlop;
    private boolean isCanDrag;
    private boolean isCheckLeftAndRight;
    private boolean isCheckTopAndBottom;

    //----双击放大与缩小
    private GestureDetector mGestureDetector;
    private boolean isScaleing;
    private List<MotionEvent> events;
    private OnClickListener onClickListener;
    private int arae_img_id = -1;


    public ZoomImageView(Context context) {
        this(context, null);
    }

    public ZoomImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        initView(context);
    }

    public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void initView(Context context) {

        setScaleType(ScaleType.MATRIX);
        mMatrix = new
                Matrix();
        mScaleGestureDetector = new
                ScaleGestureDetector(context, this);
        mGestureDetector = new
                GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                if (isScaleing || getScale() >= mMaxScale)
                    return true;
                isScaleing = true;
                float x = e.getX();
                float y = e.getY();

                if (getScale() < mMidScale) {
                    postDelayed(new AutoScaleRunnable(mMidScale, x, y), 16);
                } else {
                    postDelayed(new AutoScaleRunnable(mMinScale, x, y), 16);
                }

                return true;
            }

            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                if (onClickListener != null) {
                    onClickListener.onClick(ZoomImageView.this);
                    return true;
                }
                return false;
            }
        });
        setOnTouchListener(this);
        mTouchSlop = ViewConfiguration.get(context).
                getScaledTouchSlop();
        events = new ArrayList<>();
    }

    private class AutoScaleRunnable implements Runnable {
        /**
         * 要缩放的目标值
         */
        private float mTargetScale;
        private float x; //缩放的中心点x
        private float y; //缩放的中心点y
        private float tmpScale;

        private final float BIGGER = 1.07f;
        private final float SMALL = 0.93f;

        public AutoScaleRunnable(float mTargetScale, float x, float y) {
            this.mTargetScale = mTargetScale;
            this.x = x;
            this.y = y;

            if (getScale() < mTargetScale) {
                tmpScale = BIGGER;
            } else {
                tmpScale = SMALL;
            }
        }

        @Override
        public void run() {
            mMatrix.postScale(tmpScale, tmpScale, x, y);
            checkBorderAndCenterWhenScale();
            setImageMatrix(mMatrix);


            float currentScale = getScale();
            if ((tmpScale > 1.0f && currentScale < mTargetScale)
                    || (tmpScale < 1.0f && currentScale > mTargetScale)) {
                postDelayed(this, 16);
            } else {
                float scale = mTargetScale / currentScale;
                mMatrix.postScale(scale, scale, x, y);
                checkBorderAndCenterWhenScale();
                setImageMatrix(mMatrix);
                isScaleing = false;
            }
        }
    }


    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        log("注册了OnGlobalLayoutListener");
        getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    @SuppressLint("NewApi")
    @Override
    @SuppressWarnings("deprecation")
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        log("反注册了OnGlobalLayoutListener");
        getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }

    @Override
    public void onGlobalLayout() {
        log("执行了onGlobalLayout| NULL:" + (getDrawable() == null));
        if (getDrawable() == null || getWidth() == 0 || getHeight() == 0) return;

        if (!isInit) {
            log("初始化完毕");
            int width = getWidth();
            int height = getHeight();
            float screenWeight = height * 1.0f / width;

            int imageH = getDrawable().getIntrinsicHeight(); // 图片高度
            int imageW = getDrawable().getIntrinsicWidth(); // 图片宽度

            float imageWeight = imageH * 1.0f / imageW;
            //如果当前屏幕高宽比 大于等于 图片高宽比,就缩放图片
            if (screenWeight >= imageWeight) {
                float scale = 1.0f;
                //图片比当前View宽,但是比当前View矮
                if (imageW > width && imageH < height) {
                    scale = width * 1.0f / imageW; //根据宽度缩放
                }

                //图片比当前View窄,但是比当前View高
                if (imageH > height && imageW < width) {
                    scale = height * 1.0f / imageH; //根据高度缩放
                }

                //图片高宽都大于当前View,那么就根据最小的缩放值来缩放
                if (imageH > height && imageW > width) {
                    scale = Math.min(width * 1.0f / imageW, height * 1.0f / imageH);
                    log("max scale:" + scale);
                }

                if (imageH < height && imageW < width) {
                    scale = Math.min(width * 1.0f / imageW, height * 1.0f / imageH);
                    log("min scale:" + scale);
                }

                /**
                 * 设置缩放比率
                 */
                mMinScale = scale;
                mMidScale = mMinScale * 2;
                mMaxScale = mMinScale * 4;
                /**
                 * 把图片移动到中心点去
                 */
                int dx = getWidth() / 2 - imageW / 2;
                int dy = getHeight() / 2 - imageH / 2;

                /**
                 * 设置缩放(全图浏览模式,用最小的缩放比率去查看图片就好了)/移动位置
                 */
                mMatrix.postTranslate(dx, dy);
                mMatrix.postScale(mMinScale, mMinScale, width / 2, height / 2);
            } else {

                //将宽度缩放至屏幕比例缩放(长图,全图预览)
                float scale = width * 1.0f / imageW;
                /**
                 * 设置缩放比率
                 */
                mMaxScale = scale;
                mMidScale = mMaxScale / 2;
                mMinScale = mMaxScale / 4;

                //因为是长图浏览,所以用最大的缩放比率去加载长图
                //mMatrix.postTranslate(0, 0);
                mMatrix.postScale(mMaxScale, mMaxScale, 0, 0);
            }

            setImageMatrix(mMatrix);
            isInit = true;
        }
    }


    /**
     * 是否是Debug模式
     */
    private static boolean IS_DEBUG = true;

    /**
     * 打印日志
     *
     * @param value 要打印的日志
     */
    public static void log(String value) {
        if (IS_DEBUG)
            Log.w(TAG, value);
    }


    /**
     * 设置初始化状态为false
     */
    public void reSetState() {
        isInit = false;
        setTag(null);
        mMatrix.reset();
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (mGestureDetector.onTouchEvent(motionEvent))
            return true;

        //将触摸事件传递给ScaleGestureDetector
        if (motionEvent.getPointerCount() > 1)
            mScaleGestureDetector.onTouchEvent(motionEvent);


        float x = 0;
        float y = 0;

        int pointerCount = motionEvent.getPointerCount();

        for (int i = 0; i < pointerCount; i++) {
            x += motionEvent.getX(i);
            y += motionEvent.getY(i);
        }

        x /= pointerCount;
        y /= pointerCount;

        if (mLastPointereCount != pointerCount) {
            isCanDrag = false;
            mLastX = x;
            mLastY = y;
        }

        mLastPointereCount = pointerCount;

        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                RectF rectF = getMatrixRectF();
                if ((rectF.width() > getWidth() + 0.01f || (rectF.height() > getHeight() + 0.01f))) {
                    if ((rectF.right != getWidth()) && (rectF.left != 0)) {
                        try {
                            getParent().requestDisallowInterceptTouchEvent(true);
                        } catch (Exception e) {
                            log(e.toString());
                        }
                    }
                }
                break;
            }
            case MotionEvent.ACTION_MOVE: {

                float dx = x - mLastX;
                float dy = y - mLastY;

                if (!isCanDrag) {
                    isCanDrag = isMoveAction(dx, dy);
                }

                if (isCanDrag) {
                    RectF rectF = getMatrixRectF();

                    if (getDrawable() != null) {
                        isCheckLeftAndRight = isCheckTopAndBottom = true;

                        if (rectF.width() <= getWidth()) {
                            isCheckLeftAndRight = false;
                            dx = 0;
                        }

                        if (rectF.height() <= getHeight()) {
                            isCheckTopAndBottom = false;
                            dy = 0;
                        }

                        mMatrix.postTranslate(dx, dy);
                        checkBorderWhenTranslate();
                        setImageMatrix(mMatrix);
                    }
                }
                mLastX = x;
                mLastY = y;

                RectF rect = getMatrixRectF();
                if ((rect.width() > getWidth() + 0.01f || (rect.height() > getHeight() + 0.01f))) {
                    if ((rect.right != getWidth()) && (rect.left != 0)) {
                        try {
                            getParent().requestDisallowInterceptTouchEvent(true);
                        } catch (Exception e) {
                            log(e.toString());
                        }
                    }
                }
                break;
            }
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP: {
                mLastPointereCount = 0;
                break;
            }
        }
        return true;
    }

    /**
     * 在移动图片的时候进行边界检查
     */
    private void checkBorderWhenTranslate() {
        RectF rectF = getMatrixRectF();

        float deltaX = 0;
        float deltaY = 0;

        int width = getWidth();
        int height = getHeight();

        if (rectF.top > 0 && isCheckTopAndBottom) {
            deltaY = -rectF.top;
        }

        if (rectF.bottom < height && isCheckTopAndBottom) {
            deltaY = height - rectF.bottom;
        }


        if (rectF.left > 0 && isCheckLeftAndRight) {
            deltaX = -rectF.left;
        }

        if (rectF.right < width && isCheckLeftAndRight) {
            deltaX = width - rectF.right;
        }

        mMatrix.postTranslate(deltaX, deltaY);
        setImageMatrix(mMatrix);
    }

    /**
     * 判断是否足以触发移动事件
     *
     * @param dx
     * @param dy
     * @return
     */
    private boolean isMoveAction(float dx, float dy) {
        return Math.sqrt(dx * dx + dy * dy) > mTouchSlop;
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {

        float scaleFactor = detector.getScaleFactor();//获取用户手势判断出来的缩放值
        float scale = getScale();

        /**
         * 没有图片
         */
        if (getDrawable() == null) return true;

        //缩放范围控制
        if ((scale < mMaxScale && scaleFactor > 1.0f) || (scale > mMinScale && scaleFactor < 1.0f)) {
            if (scaleFactor * scale < mMinScale) {
                scaleFactor = mMinScale / scale;
            }

            if (scale * scaleFactor > mMaxScale) {
                scaleFactor = mMaxScale / scale;
            }

            mMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
            checkBorderAndCenterWhenScale();
            setImageMatrix(mMatrix);
        }
        return true;
    }

    /**
     * 在缩放的时候进行边界,位置 检查
     */
    private void checkBorderAndCenterWhenScale() {
        RectF rectF = getMatrixRectF();

        float deltaX = 0;
        float deltaY = 0;

        int width = getWidth();
        int height = getHeight();

        if (rectF.width() >= width) {
            if (rectF.left > 0)
                deltaX = -rectF.left;
            if (rectF.right < width)
                deltaX = width - rectF.right;
        }

        if (rectF.height() >= height) {
            if (rectF.top > 0)
                deltaY = 0;
            if (rectF.bottom < height)
                deltaY = height - rectF.bottom;
        }

        if (rectF.width() < width) {
            deltaX = width / 2f - rectF.right + rectF.width() / 2;
        }

        if (rectF.height() < height) {
            deltaY = height / 2f - rectF.bottom + rectF.height() / 2;
        }

        mMatrix.postTranslate(deltaX, deltaY);
        setImageMatrix(mMatrix);
    }

    /**
     * 获取图片放大缩小后的宽高/top/left/right/bottom
     *
     * @return
     */
    private RectF getMatrixRectF() {
        RectF rectF = new RectF();
        Drawable drawable = getDrawable();

        if (drawable != null) {
            rectF.set(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            mMatrix.mapRect(rectF);
        }

        return rectF;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
        return true; //缩放开始,返回true 用于接收后续时间
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {

    }

    /**
     * 获取当前的缩放比率
     *
     * @return
     */
    private float getScale() {
        float[] values = new float[9];
        mMatrix.getValues(values);
        return values[Matrix.MSCALE_X];
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        reSetState();
        super.setImageBitmap(bm);
    }

    @Override
    public void setImageResource(int resId) {
        reSetState();
        super.setImageResource(resId);
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        reSetState();
        super.setImageDrawable(drawable);
    }

    @Override
    public void setOnClickListener(OnClickListener l) {
        this.onClickListener = l;
    }
}

       然后用Glide.with(this).load(url).into(zoomImageView);加载网络上的图片,就可以自由放大缩小图片了。布局代码如下

<com.wbkj.mss.UiView.weight.ZoomImageView
    android:id="@+id/iv_zoom"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
然后就是点击下载,Glide默认是有缓存的,下载也就是把缓存存到本地。在onclick中执行onDownload()方法就可以了。
class DownLoadImageService implements Runnable {
    private String url;
    private Context context;
    private ImageDownLoadCallBack callBack;

    public DownLoadImageService(Context context, String url, ImageDownLoadCallBack callBack) {
        this.url = url;
        this.callBack = callBack;
        this.context = context;
    }

    @Override
    public void run() {
        File file = null;
        try {
            file = Glide.with(context)
                    .load(url)
                    .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
                    .get();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (file != null) {
                callBack.onDownLoadSuccess(file);
            } else {
                callBack.onDownLoadFailed();
            }
        }
    }
}
/**
 * 执行单线程列队执行
 */
public void runOnQueue(Runnable runnable) {
    if (singleExecutor == null) {
        singleExecutor = Executors.newSingleThreadExecutor();
    }
    singleExecutor.submit(runnable);
}

/**
 * 启动图片下载线程
 */
private void onDownLoad() {
    DownLoadImageService service = new DownLoadImageService(this, url, new ImageDownLoadCallBack() {
                @Override
                public void onDownLoadSuccess(File file) {
                        try {
                            int bytesum = 0;
                            int byteread = 0;
                            File imgfile = new File(savaPath); //Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+"yida"+url.substring(url.lastIndexOf("/"));我用的保存文件的地址

                            InputStream inputStream = new FileInputStream(file);
                            OutputStream outputStream = new FileOutputStream(imgfile);
                            byte[] buffer = new byte[1000];
                            int length;
                            while ( (byteread = inputStream.read(buffer)) != -1) {
                                bytesum += byteread; //字节数 文件大小
                                outputStream.write(buffer, 0, byteread);
                            }
                            outputStream.flush();
                            outputStream.close();
                            inputStream.close();
                            handle.sendEmptyMessageDelayed(0,0); //保存成功后采用handler发送消息到主线程。进行toast提示用户
                    } catch (Exception e) {
                            
                            e.printStackTrace();
                        }
                    }

                @Override
                public void onDownLoadFailed() {
                    
                }
            });
    //启动图片下载线程
    runOnQueue(service);
}

private Handler handle = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        handle.removeMessages(0);
        Toast.makeText(ZoomImageActivity.this, "保存成功,保存在yida文件夹下", Toast.LENGTH_SHORT).show();
        mDialog.dismiss();
    }
};

第一篇博文就写完了。貌似文笔有点混乱,还请多多包涵。效果如图

最后

以上就是无心月饼为你收集整理的Android ZoomImageView手势缩放拖动图片,并将Glide加载的网络图片保存到本地。的全部内容,希望文章能够帮你解决Android ZoomImageView手势缩放拖动图片,并将Glide加载的网络图片保存到本地。所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部