Android 图片的放大缩小拖拉

package com.example.ImageView;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.*;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by Administrator on 2015/1/4.
 * <p/>
 * 实现图片缩小放大拖拉效果
 */
public class MImageView extends View {
    private Paint mPaint;//画笔
    private Drawable mDrawable;
    private Rect mDrawableRect = new Rect();
    private Rect mRect = new Rect();//原始图片位置大小
    private Context mContext;
    private float mRation_WH = 0;
    private float mOldX = 0, mOldY = 0;
    private boolean isFirst = true;
    private int SINGALDOWN = 1;// 单点按下
    private int mStatus = 0;
    private int offsetWidth = 0;
    private int offsetHeight = 0;
    private GestureDetector tapDetector;//实现双击放大缩小功能
    private float beforeLenght, afterLenght;// 两触点距离
    private float scale_temp = 1;// 缩放比例
    private MODE mode = MODE.NONE;
    private OnMeasureListener onMeasureListener;
    private boolean status = true;


    public MImageView(Context context) {
        super(context);
        Init(context);

    }

    public MImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Init(context);
    }

    public void setOnMeasureListener(OnMeasureListener onMeasureListener) {
        this.onMeasureListener = onMeasureListener;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0 && status) {
            if (onMeasureListener != null) {
                onMeasureListener.onMeasureSize(getMeasuredWidth(), getMeasuredHeight());
                status = false;
            }
        }
    }

    public interface OnMeasureListener {
        public void onMeasureSize(int width, int height);
    }


    private void Init(Context context) {//初始化控件属性
        this.mContext = context;
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextSize(35.0f);

        tapDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                doScaleAnim();
                return true;
            }
        });
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        try {
            if (mDrawable == null || mDrawable.getIntrinsicHeight() == 0
                    || mDrawable.getIntrinsicWidth() == 0) {
                return;
            }
            setBounds();
            mDrawable.draw(canvas);
        } catch (Exception e) {
        }

    }

    /**
     * 模式 NONE:无 DRAG:拖拽. ZOOM:缩放
     *
     * @author zhangjia
     */
    private enum MODE {
        NONE, DRAG, ZOOM

    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        if (!tapDetector.onTouchEvent(event)) {
            switch (event.getAction() & event.getActionMasked()) {
                case MotionEvent.ACTION_DOWN:
                    mStatus = SINGALDOWN;
                    mOldX = event.getX();
                    mOldY = event.getY();
                    mode = MODE.DRAG;
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    mode = MODE.ZOOM;
                    beforeLenght = getDistance(event);// 获取两点的距离
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    mOldX = event.getX();
                    mOldX = event.getY();
                    mode = MODE.NONE;
                    break;
                case MotionEvent.ACTION_UP:
                    if (mDrawableRect.height() < mRect.height() && mDrawableRect.width() < mRect.width())
                        doScaleAnim();
                    else {
                        up();
                        invalidate();
                    }
                    getParent().requestDisallowInterceptTouchEvent(false);
                    mStatus = 0;
                    mode = MODE.NONE;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mode == MODE.DRAG) {//移动状态
                        if (getWidth() < mDrawableRect.width()) {
                            getParent().requestDisallowInterceptTouchEvent(true);
                            moveDrag(event);
                        } else {
                            getParent().requestDisallowInterceptTouchEvent(false);
                            return false;
                        }
                    }
                    if (mode == MODE.ZOOM) {//判断是否为缩放状态
                        getParent().requestDisallowInterceptTouchEvent(true);
                        moveZoom(event);
                    }
                    Log.i("wade", mDrawableRect.toString() + "width:" + getWidth() + "height:" + getHeight());
                    break;
                default:
                    break;
            }
        } else {
            return false;
        }
        return true;
    }


    /**
     * 获取两点的距离 *
     */

    float getDistance(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /**
     * 手指抬起的时候回弹边界*
     */
    private void up() {
        int left, right, top, bottom;
        left = mDrawableRect.left;
        right = mDrawableRect.right;
        top = mDrawableRect.top;
        bottom = mDrawableRect.bottom;
        offsetWidth = 0;
        offsetHeight = 0;
        if (mDrawableRect.width() > getWidth() && mDrawableRect.left >= 0) {
            offsetWidth = -mDrawableRect.left;
        }
        if (mDrawableRect.height() > getHeight() && mDrawableRect.top >= 0) {
            offsetHeight = -mDrawableRect.top;
        }
        if (mDrawableRect.width() > getWidth() && mDrawableRect.right <= getWidth()) {
            offsetWidth = getWidth() - mDrawableRect.right;
        }
        if (mDrawableRect.height() > getHeight() && mDrawableRect.bottom <= getHeight()) {
            offsetHeight = getHeight() - mDrawableRect.bottom;
        }
        if (mDrawableRect.width() < getWidth()) {
            left = (getWidth() - mDrawableRect.width()) / 2;
            offsetWidth = 0;
            mDrawableRect.set(left, top, left + mDrawableRect.width(), bottom);
        }
        if (mDrawableRect.height() < getHeight()) {
            top = (getHeight() - mDrawableRect.height()) / 2;
            offsetHeight = 0;
            mDrawableRect.set(left, top, right, top + mDrawableRect.height());
        }
        mDrawableRect.offset(offsetWidth, offsetHeight);
    }

    private void moveDrag(MotionEvent event) {
        if (mStatus == SINGALDOWN) {
            offsetWidth = (int) (event.getX() - mOldX);
            offsetHeight = (int) (event.getY() - mOldY);
            mOldX = event.getX();
            mOldY = event.getY();
            if (mDrawableRect.width() < getWidth()) {
                offsetWidth = 0;
            }

            if (mDrawableRect.height() < getHeight()) {
                offsetHeight = 0;
            }

            mDrawableRect.offset(offsetWidth, offsetHeight);
            invalidate();
        }
    }

    private void moveZoom(MotionEvent event) {//用于缩放布局的方法
        afterLenght = getDistance(event);// 获取两点的距离
        float gapLenght = afterLenght - beforeLenght;// 变化的长度
        if (Math.abs(gapLenght) > 5f) {
            scale_temp = afterLenght / beforeLenght;// 求的缩放的比例
        }
        Log.i("wade", "gapLenght" + gapLenght + "");
        int disX = (int) (mDrawableRect.width() * Math.abs(1 - scale_temp)) / 4;// 获取缩放水平距离
        int disY = (int) (mDrawableRect.height() * Math.abs(1 - scale_temp)) / 4;// 获取缩放垂直距离
        if (beforeLenght < afterLenght) {
            if (scale_temp > 1 && mDrawableRect.width() < mContext.getResources()
                    .getDisplayMetrics().widthPixels * 3) {
                mDrawableRect.set(mDrawableRect.left - disX,
                        mDrawableRect.top - disY,
                        mDrawableRect.right + disX,
                        mDrawableRect.bottom + disY);
                invalidate();
            }
        } else {
            if (scale_temp < 1 && mDrawableRect.width() > mContext.getResources()
                    .getDisplayMetrics().widthPixels / 2) {
                mDrawableRect.set(mDrawableRect.left + disX,
                        mDrawableRect.top + disY,
                        mDrawableRect.right - disX,
                        mDrawableRect.bottom - disY);
                invalidate();
            }
        }
        beforeLenght = afterLenght;
        scale_temp = 1;
    }


    /**
     * 设置mDrawable的位置*
     */
    public void setBounds() {
        if (isFirst) {
            mRation_WH = (float) mDrawable.getIntrinsicWidth()
                    / (float) mDrawable.getIntrinsicHeight();
            int px_w = Math.min(getWidth(),
                    dip2px(mContext, mDrawable.getIntrinsicWidth()));
            int px_h = (int) (px_w / mRation_WH);
            int left = (getWidth() - px_w) / 2;
            int top = (getHeight() - px_h) / 2;
            int right = px_w + left;
            int bottom = px_h + top;
            mRect.set(left, top, right, bottom);
            mDrawableRect.set(left, top, right, bottom);
            isFirst = false;
        }
        mDrawable.setBounds(mDrawableRect);
    }


    public Drawable getMDrawable() {
        return mDrawable;
    }

    public void setMDrawable(Drawable mDrawable) {
        this.mDrawable = mDrawable;
        postInvalidate();
    }

    public void setImageBitmap(Bitmap mBitmap) {
        if (mBitmap != null) {
            setMDrawable(new BitmapDrawable(getResources(), mBitmap));
        }

    }

    public void setMDrawable(Drawable mDrawable, Rect rect) {
        this.mDrawable = mDrawable;
        postInvalidate();//第一次post为了计算图片的大小和位置
        if (rect != null) {
            mDrawableRect.set(rect);
            postInvalidate();
            doScaleAnim();
        }
    }

    public void setImageBitmap(Bitmap mBitmap, Rect rect) {
        if (mBitmap != null) {
            setMDrawable(new BitmapDrawable(getResources(), mBitmap), rect);
        }

    }

    public int dip2px(Context context, int value) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (value * scale + 0.5f);
    }

    /**
     * 缩放动画处理
     */
    public void doScaleAnim() {
        MyAsyncTask myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute();
    }

    /**
     * 回缩动画執行
     */
    class MyAsyncTask extends AsyncTask<Void, Integer, Void> {
        private int current_Width, current_Height, width;

        private int left, top, right, bottom;

        private float scale_WH;// 宽高的比例


        private float STEP = 8f;// 步伐

        private float step_H, step_V;// 水平步伐,垂直步伐

        private int status;//1放大到MAX_W宽度,2缩小原始大小,3放大成原始大小
        private boolean change = true;//用来检测是否还能缩放


        public MyAsyncTask() {

        }

        @Override
        protected Void doInBackground(Void... params) {
            change = true;
            current_Width = mDrawableRect.width();
            current_Height = mDrawableRect.height();
            scale_WH = (float) current_Height / current_Width;
            step_H = STEP;
            step_V = scale_WH * STEP;
            left = mDrawableRect.left;
            top = mDrawableRect.top;
            right = mDrawableRect.right;
            bottom = mDrawableRect.bottom;
            if (mDrawableRect.height() == mRect.height() && mDrawableRect.width() == mRect.width()) {
                status = 1;
                width = mRect.width() * 2;
            } else {
                if (mDrawableRect.height() > mRect.height() && mDrawableRect.width() > mRect.width()) {
                    status = 2;
                    width = mRect.width();
                } else {
                    if (mDrawableRect.height() < mRect.height() && mDrawableRect.width() < mRect.width()) {
                        status = 3;
                        width = mRect.width();
                    }
                }
            }

            while (change) {
                switch (status) {
                    case 1:
                        left -= step_H;
                        top -= step_V;
                        right += step_H;
                        bottom += step_V;
                        current_Width += 2 * step_H;
                        if (current_Width >= width) change = false;
                        break;
                    case 2:
                        left += step_H;
                        top += step_V;
                        right -= step_H;
                        bottom -= step_V;
                        current_Width -= 2 * step_H;
                        if (current_Width <= width) {
                            left = mRect.left;
                            top = mRect.top;
                            right = mRect.right;
                            bottom = mRect.bottom;
                            change = false;
                        }
                        break;
                    case 3:
                        left -= step_H;
                        top -= step_V;
                        right += step_H;
                        bottom += step_V;
                        current_Width += 2 * step_H;
                        if (current_Width >= width) {
                            left = mRect.left;
                            top = mRect.top;
                            right = mRect.right;
                            bottom = mRect.bottom;
                            change = false;
                        }
                        break;

                }
                mDrawableRect.set(left, top, right, bottom);
                Message.obtain(handler, 1).sendToTarget();
                try {
                    Thread.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }


        @Override
        protected void onProgressUpdate(final Integer... values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            up();
            invalidate();
        }
    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    invalidate();
                    break;
            }
        }
    };
}

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。