手势控制控件 的缩放,平移和旋转:

本文探讨了在手势控制中如何实现地图控件(mapView)的缩放、平移和旋转。通过在父控件设置setOnTouchListener与在mapView中重写onTouchEvent方法的比较,发现setOnTouchListener提供的交互体验更流畅。尽管代码基本相同,但在setOnTouchListener中执行的手势操作反应更快。为使onTouchEvent达到同样效果,需要对其进行调整。同时,文章提到了onTouchEvent与setOnTouchListener的关系,即onTouch方法返回true会阻止onTouchEvent的执行,返回false则允许执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

手势控制控件的缩放,平移和旋转:

mapView是要移动的控件,TouchLayout是手势控制的区域,具体代码如下:

touchLayout.setOnTouchListener(new TouchListener());
class TouchListener implements View.OnTouchListener {
        //以下代码为地图的手势控制
        private final int DRAG = 1;
        private final int ZOOM = 2;
        private final int NONE = 0;
        private int mode = NONE;
        private float x_down = 0;
        private float y_down = 0;

        private PointF start = new PointF();
        private PointF mid = new PointF();

        private float oldScale = 1;
        private float oldDist = 1f;
        private float oldAngle = 0;
        private float oldRotation = 0;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    mode = DRAG;
                    x_down = event.getX();
                    y_down = event.getY();
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    mode = ZOOM;
                    oldDist = spacing(event);
                    oldAngle = angle(event);
                    midPoint(mid, event);
                    break;

                case MotionEvent.ACTION_MOVE:
                    if (mode == ZOOM) {
                        //缩放
                        float newDist = spacing(event);
                        float newScale = (newDist) / oldDist * oldScale;

                        Log.i("map缩放", "onTouchEvent: " + newScale + "  ");
                        mapView.setScaleX(newScale);
                        mapView.setScaleY(newScale);

                        oldDist = newDist;
                        oldScale = newScale;

                        //旋转
                        float newAngle = angle(event);
                        float newRotation = newAngle - oldAngle + oldRotation;
                        Log.i("map旋转", "onTouch: " + newRotation + "  " + oldRotation);
                        mapView.setRotation(newRotation);

                        oldRotation =  newRotation;
                        oldAngle = newAngle;


                    } else if (mode == DRAG) {
                        float d_x = event.getX() - x_down;
                        float d_y = event.getY() - y_down;
                        Log.i("map平移", "onTouchEvent: " + d_x + "  " + d_y);

                        mapView.offsetLeftAndRight((int) (0.5 + d_x));
                        mapView.offsetTopAndBottom((int) (0.5 + d_y));

                        x_down = event.getX();
                        y_down = event.getY();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_POINTER_UP:
                    mode = NONE;
                    break;
            }
            return true;
        }

        // 触碰两点间距离
        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 void midPoint(PointF point, MotionEvent event) {
            float x = event.getX(0) + event.getX(1);
            float y = event.getY(0) + event.getY(1);
            point.set(x / 2, y / 2);
        }

        // 取旋转角度
        private float angle(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);
        }
    }

我也试过在mapview中重写onTouchEvent方法,主要代码和以上代码基本几乎完全相同,就不再贴出来了。但是,却发现一个问题,如果基本原封不动的照抄以上代码,在mapview中重写onTouchEvent方法的效果没有在在父控件调用setOnTouchListener方法的效果好。简单来说,完全相同的代码,在setOnTouchListener方法中要更流畅,无论是缩放,还是平移,都明显比onTouchEvent方法的效果要快。。如果要是两者达到相同的体验效果,需对onTouchEvent方法做少许修改。。。不知道是什么原因~

参考文章:

https://blog.youkuaiyun.com/eieihihi/article/details/45668189

https://blog.youkuaiyun.com/happy_bug/article/details/7895244

另外,附上一下onTouchEvent和setOnTouchListener的关系:

1、如果setOnTouchListener中的onTouch方法返回值是true则onTouchEvent方法将不会被执行;

2、只有当setOnTouchListener中的onTouch方法返回值是false时onTouchEvent方法才被执行。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值