通过手势实现Android自定义View的缩放

来源:互联网 发布:淘宝卖衣服店铺名 编辑:程序博客网 时间:2024/06/05 20:44

这里使用了一个自定义View–TouchImageView来实现图片的缩放,代码如下:

TouchImageView:

package com.example.test;/** * Created by agint_bin on 2016/7/20. */import android.content.Context;import android.graphics.Matrix;import android.graphics.PointF;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.ScaleGestureDetector;import android.view.View;import android.widget.ImageView;public class TouchImageView extends ImageView {    Matrix matrix;    // We can be in one of these 3 states    static final int NONE = 0;  //初始    static final int DRAG = 1;  //拖动    static final int ZOOM = 2;  //放大    int mode = NONE;    // Remember some things for zooming    PointF last = new PointF();    PointF start = new PointF();    float minScale = 1f;    float maxScale = 3f;    float[] m;    int viewWidth, viewHeight;    static final int CLICK = 3;    float saveScale = 1f;    protected float origWidth, origHeight;    int oldMeasuredWidth, oldMeasuredHeight;    ScaleGestureDetector mScaleDetector;    Context context;    //默认构造函数    public TouchImageView(Context context) {        super(context);        sharedConstructing(context);    }    public TouchImageView(Context context, AttributeSet attrs) {        super(context, attrs);        sharedConstructing(context);    }    private void sharedConstructing(Context context) {        super.setClickable(true);        this.context = context;        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());        matrix = new Matrix();        m = new float[9];        setImageMatrix(matrix);        setScaleType(ScaleType.MATRIX);        setOnTouchListener(new OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                mScaleDetector.onTouchEvent(event);                PointF curr = new PointF(event.getX(), event.getY());                switch (event.getAction()) {                    case MotionEvent.ACTION_DOWN:                        last.set(curr);  //当前位置                        start.set(last);  //开始点                        mode = DRAG;                        break;                    case MotionEvent.ACTION_MOVE:    //移动事件                        if (mode == DRAG) {                            float deltaX = curr.x - last.x;                            float deltaY = curr.y - last.y;                            float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);                            float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);                            matrix.postTranslate(fixTransX, fixTransY);                            fixTrans();                            last.set(curr.x, curr.y);                        }                        break;                    case MotionEvent.ACTION_UP:                        mode = NONE;                        int xDiff = (int) Math.abs(curr.x - start.x);                        int yDiff = (int) Math.abs(curr.y - start.y);                        if (xDiff < CLICK && yDiff < CLICK)                            performClick();                        break;                    //有手指离开屏幕,但屏幕还有触点(手指)                     case MotionEvent.ACTION_POINTER_UP:                        mode = NONE;                        break;                }                setImageMatrix(matrix);                invalidate();                return true; // indicate event was handled            }        });    }    public void setMaxZoom(float x) {        maxScale = x;    }    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {        @Override        public boolean onScaleBegin(ScaleGestureDetector detector) {            mode = ZOOM;            return true;        }        @Override        public boolean onScale(ScaleGestureDetector detector) {            float mScaleFactor = detector.getScaleFactor();            float origScale = saveScale;            saveScale *= mScaleFactor;            if (saveScale > maxScale) {                saveScale = maxScale;                mScaleFactor = maxScale / origScale;            } else if (saveScale < minScale) {                saveScale = minScale;                mScaleFactor = minScale / origScale;            }            if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)                matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);            else                matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());            fixTrans();            return true;        }    }    void fixTrans() {        matrix.getValues(m);        float transX = m[Matrix.MTRANS_X];        float transY = m[Matrix.MTRANS_Y];        float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);        float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);        if (fixTransX != 0 || fixTransY != 0)            matrix.postTranslate(fixTransX, fixTransY);    }    float getFixTrans(float trans, float viewSize, float contentSize) {        float minTrans, maxTrans;        if (contentSize <= viewSize) {            minTrans = 0;            maxTrans = viewSize - contentSize;        } else {            minTrans = viewSize - contentSize;            maxTrans = 0;        }        if (trans < minTrans)            return -trans + minTrans;        if (trans > maxTrans)            return -trans + maxTrans;        return 0;    }    float getFixDragTrans(float delta, float viewSize, float contentSize) {        if (contentSize <= viewSize) {            return 0;        }        return delta;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        viewWidth = MeasureSpec.getSize(widthMeasureSpec);        viewHeight = MeasureSpec.getSize(heightMeasureSpec);        //        // Rescales image on rotation        //        if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight                || viewWidth == 0 || viewHeight == 0)            return;        oldMeasuredHeight = viewHeight;        oldMeasuredWidth = viewWidth;        if (saveScale == 1) {            //Fit to screen.            float scale;            Drawable drawable = getDrawable();            if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)                return;            int bmWidth = drawable.getIntrinsicWidth();            int bmHeight = drawable.getIntrinsicHeight();            Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);            float scaleX = (float) viewWidth / (float) bmWidth;            float scaleY = (float) viewHeight / (float) bmHeight;            scale = Math.min(scaleX, scaleY);            matrix.setScale(scale, scale);            // Center the image            float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);            float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);            redundantYSpace /= (float) 2;            redundantXSpace /= (float) 2;            matrix.postTranslate(redundantXSpace, redundantYSpace);            origWidth = viewWidth - 2 * redundantXSpace;            origHeight = viewHeight - 2 * redundantYSpace;            setImageMatrix(matrix);        }        fixTrans();    }}

MainActivity:

package com.example.test;import android.app.Activity;import android.os.Bundle;import android.widget.LinearLayout;public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TouchImageView img = (TouchImageView) findViewById(R.id.image);        img.setImageResource(R.drawable.modern);        img.setMaxZoom(4f);    }}

main.xml:

<?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">    <LinearLayout        android:id="@+id/root"        android:orientation="vertical"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="@drawable/gridding">    <com.example.test.TouchImageView       <!--这里特别注意,使用TouchImageViewz就要这样写-->        android:id="@+id/image"        android:layout_height="match_parent"        android:layout_width="wrap_content" />    </LinearLayout>   </LinearLayout>
0 0
原创粉丝点击