Android 放大缩小容器-ScalableViewConta

2021-01-15  本文已影响0人  程序猿小钟

前言

作为一个Android开发,当系统控件满足不了业务需求的时候,就需要程序猿自己自定义控件或者容器。所以自定义控件、自定义容器,是我们必须掌握的技术。本次,程序猿小钟就为大家介绍一下自定义的放大缩小容器,并粗略的介绍一下容器中用到的GestureDetector和ScaleGestureDetector,如果大家想要更加深入了解这两个类的话,可以自己阅读一下源码。

手势工具类GestureDetector

GestureDetector类主要是用于识别一些特定的动作手势,例如单击、双击、长按等。只需要在容器中初始化并且在onTouchEvent事件中调用GestureDetector.onTouchEvent(motionEvent),并通过GestureDetector中的接口SimpleOnGestureListener监听到各种手势的回调。

SimpleOnGestureListener是GestureDetector的内部类,主要的方法有:

缩放手势工具类ScaleGestureDetector

ScaleGestureDetector类主要是用于识别缩放手势的工具。使用方式也是只需要在容器初始化并且在onTouchEvent事件中调用ScaleGestureDetector.onTouchEvent(motionEvent),并通过ScaleGestureDetector中的接口SimpleOnScaleGestureListener监听到缩放手势的回调。

SimpleOnScaleGestureListener是ScaleGestureDetector的内部类,方法有【监听缩放手势开始回调】、【监听缩放手势回调】、【监听缩放手势结束回调】:

放大缩小容器ScalableViewContainer

/**

* 放大缩小容器(Android7以上适用)

*/

public class ScalableViewContainer extends FrameLayout {

    //常量定义

    private final float MIN_SCALE =1.0f;

    private final float MID_SCALE =1.75f;

    private final float MAX_SCALE =3.0f;

    //手势

    private GestureDetector gestureDetector;

    //缩放手势

    private ScaleGestureDetector scaleDetector;

    private int width; // 原始宽度

    private int height; // 原始高度

    private float curScale =1.0f; // 当前缩放比例

    private float translateX; // 当前X偏移

    private float translateY; // 当前Y偏移

    private float minTransX; // 最小X偏移

    private float maxTransX; // 最大X偏移

    private float minTransY; // 最小Y偏移

    private float maxTransY; // 最大Y偏移

    public ScalableViewContainer(@NonNull Context context) {

        this(context, null);

    }

    public ScalableViewContainer(@NonNull Context context, @Nullable AttributeSet attrs) {

        this(context, attrs, 0);

    }

    public ScalableViewContainer(@NonNull Context context, @Nullable AttributeSet attrs, int         defStyleAttr) {

        super(context, attrs, defStyleAttr);

        //初始化手势工具类,自定义监听

        gestureDetector =new GestureDetector(context, new CustomOnGestureListener());

        scaleDetector =new ScaleGestureDetector(context, new                 CustomOnScaleGestureListener());

    }

    /**

    * 重置

    */

    public void resetScale() {

        setScale(0);

    }

    @Override

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

        super.onSizeChanged(w, h, oldw, oldh);

        width = w;

        height = h;

    }

    /**

    * 触摸事件

    */

    @Override

    public boolean onTouchEvent(MotionEvent ev) {

        scaleDetector.onTouchEvent(ev);

        gestureDetector.onTouchEvent(ev);

        return true;

    }

    /**

    *  设置缩放

    */

    private void setScale(float scale) {

        float oldScale =curScale;

       if (scale <  MIN_SCALE) {

            curScale =MIN_SCALE;

        }else if (scale >MAX_SCALE) {

            curScale =MAX_SCALE;

        }else {

            curScale = scale;

        }

        if (oldScale !=curScale) {

            getChild().setScaleX(curScale);

            getChild().setScaleY(curScale);

            updateTrans();

        }

}

    /**

    *  缩放后调整偏移

    */

    private void updateTrans() {

        minTransX = -width * (curScale -1) /2;

        maxTransX =width * (curScale -1) /2;

        minTransY = -height * (curScale -1) /2;

        maxTransY =height * (curScale -1) /2;

        setTrans(translateX, translateY);

    }

    /**

    * 避免缩放时出现黑边

    */

    private void setTrans(float transX, float transY) {

           if (transX < minTransX) {

                translateX =minTransX;

           }else if (transX >maxTransX) {

                translateX =maxTransX;

            }else {

                translateX = transX;

            }

             if (transY < minTransY) {

                translateY =minTransY;

             }else if (transY >maxTransY) {

                translateY =maxTransY;

             }else {

                translateY = transY;

              }

            getChild().setTranslationX(translateX);

            getChild().setTranslationY(translateY);

    }

    /**

    * 获取容器中首个控件

    */

    private View getChild() {

            return getChildAt(0);

    }

    /**

    * 缩放手势监听

    */

    private class CustomOnScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

        @Override

        public boolean onScale(ScaleGestureDetector detector) {

               if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){

                    float tempScale =curScale * detector.getScaleFactor();

                    setScale(tempScale);

                    return true;

                }else{

                    return false;

                }

    }

}

    /**

    * 手势监听

    */

    private class CustomOnGestureListener extends GestureDetector.SimpleOnGestureListener {

        /**

        * 用户按下触摸屏,并拖动

        */

        @Override

        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){

                    float transX =translateX -= distanceX;

                    float transY =translateY -= distanceY;

                    setTrans(transX, transY);

                    return true;

            }else{

                    return false;

            }

    }

        /**

        *  用户双击屏幕

        */

        @Override

        public boolean onDoubleTap(MotionEvent e) {

           //因Android7以下的手机缩放方法异常,把缩放功能控制在Android7以上的手机才能使用

            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){

                float tempScale;

                if (curScale >=MIN_SCALE && curScale < MID_SCALE){

                    tempScale =MID_SCALE;

                }else if (curScale >=MID_SCALE && curScale < MAX_SCALE){

                    tempScale =MAX_SCALE;

                }else {

                    tempScale =MIN_SCALE;

                }

                    setScale(tempScale);

                    return true;

                }else{

                    return false;

                }

        }

    }

}

使用方式

                                        2021年1月15日程序猿小钟带着ScalableViewContainer到此一游~

上一篇 下一篇

猜你喜欢

热点阅读