Android 安卓:用手指在画布上缩放圆圈

Android 安卓:用手指在画布上缩放圆圈,android,android-canvas,scaling,Android,Android Canvas,Scaling,我现在可以在画布上放置和拖动圆圈,但我很难理解如何允许用户用捏的手势缩放圆圈 这些圆是用“canvas.drawCircle(x,y,radius,paint)”绘制的。我最初的想法是用一个自定义的“SimpleOnScaleGetStureListener”来听捏手势,然后将选定圆的半径乘以一个比例因子。这产生了一些相当不可预测的结果,通过用两个手指快速敲击,圆圈被缩放成微小或史诗般的比例 以下是我的自定义侦听器: private class ScaleListener extends Sca

我现在可以在画布上放置和拖动圆圈,但我很难理解如何允许用户用捏的手势缩放圆圈

这些圆是用“canvas.drawCircle(x,y,radius,paint)”绘制的。我最初的想法是用一个自定义的“SimpleOnScaleGetStureListener”来听捏手势,然后将选定圆的半径乘以一个比例因子。这产生了一些相当不可预测的结果,通过用两个手指快速敲击,圆圈被缩放成微小或史诗般的比例

以下是我的自定义侦听器:

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

            @Override
            public boolean onScale(ScaleGestureDetector detector){
                mScaleFactor *= detector.getScaleFactor()

                if (isCircleToolSelected) {
                    // Checks if gesture was made inside of an existing circle
                    // CircleDrawing is a private class that holds x,y,radius,paint values
                    CircleDrawing circle = getCircle(detector.getFocusX(), 
                                                     detector.getFocusY());

                    if (circle != null) {
                       touchedCircle.radius *= mScaleFactor;
                    }
                }
                return true;
            }
        }
这会检测到手势,并知道挤压是否在我画布上的一个圆圈内,但应用的缩放完全失控,无法使用

我只尝试在当前和以前的比例因子之间的差异超过某个阈值时进行缩放,但这只会使缩放更不可预测,更不稳定


如果有人已经实现了类似的东西,我会喜欢一些方向

选择“圆”时必须获得比例因子

 private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {

            if (isCircleToolSelected) {
                mScaleFactor *= detector.getScaleFactor()
                // Checks if gesture was made inside of an existing circle
                // CircleDrawing is a private class that holds x,y,radius,paintvalues
                CircleDrawing circle = getCircle(detector.getFocusX(), 
                                                 detector.getFocusY());

                if (circle != null) {
                   touchedCircle.radius *= mScaleFactor;
                }
            }
        return true;
    }
}

回答我自己的问题,以防其他人确信您必须使用ScaleFactor缩放所有内容。对于圆的基本缩放,您只需要找到getCurrentSpan()的当前值和上一个值之间的差异

这是我最后使用的代码:

//Used elsewhere to detect if we've touched an existing circle
CircleDrawing touchedCircle;

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

        private float lastSpan;
        private float lastRadius;

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {

            //If the user has not already selected a circle
            if (null == touchedCircle) {

                // Check if we started scale gesture within existing circle
                touchedCircle = getCircle(detector.getFocusX(), detector.getFocusY());
            }

            //If a circle has been selected, save radius and span
            if (touchedCircle != null) {
                lastRadius = touchedCircle.radius;
                lastSpan = detector.getCurrentSpan();
            }
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector){

            //If the user has the shapes tool selected - handled elsewhere
            if (isShapesSelected) {

                //If the user is touching a circle
                if (touchedCircle != null) {

                    //Value used to calculate new radius
                    float currentSpan = detector.getCurrentSpan();
                    float diameterDiff = currentSpan - lastSpan;

                    //Keep track of scaling direction for min and max sizes
                    boolean scalingUp = diameterDiff > 0;

                    //Only scale within radius sizes between 150 and 500
                    //Likely will change these values to relate to size of canvas
                    if ((!scalingUp && (lastRadius >= 150)) || (scalingUp && (lastRadius < 500))) {

                        //Calculate and set new radius
                        touchedCircle.radius += (diameterDiff)/2;

                        //Save radius and span for next frame
                        lastRadius = touchedCircle.radius;
                        lastSpan = detector.getCurrentSpan();
                    }
                }
            }
            return true;
        }
    }
//在别处用于检测我们是否接触到现有圆
圆形绘制接触圆;
私有类ScaleListener扩展了scalegestruedetector.SimpleOnScalegestrueListener{
私人股本;
私有浮动半径;
@凌驾
公共布尔onScaleBegin(ScaleGetStereDetector检测器){
//如果用户尚未选择圆
如果(空==接触圆){
//检查我们是否在现有圆圈内开始缩放手势
touchedCircle=getCircle(detector.getFocusX(),detector.getFocusY());
}
//如果选择了圆,请保存半径和跨度
if(touchedCircle!=null){
lastRadius=接触圆半径;
lastSpan=检测器。getCurrentSpan();
}
返回true;
}
@凌驾
公共布尔标度(scalegestruedetector检测器){
//如果用户已选择形状工具-在其他位置处理
如果(已选择IsShapessected){
//如果用户正在触摸一个圆
if(touchedCircle!=null){
//用于计算新半径的值
float currentSpan=检测器。getCurrentSpan();
浮动直径diff=当前跨度-最后跨度;
//跟踪最小和最大尺寸的缩放方向
布尔缩放p=直径diff>0;
//仅在半径大小介于150和500之间的范围内缩放
//可能会更改这些值,使其与画布的大小相关
如果((!scalingUp&&(lastRadius>=150))| |(scalingUp&&(lastRadius<500))){
//计算并设置新半径
接触圆半径+=(直径差)/2;
//为下一帧保存半径和跨度
lastRadius=接触圆半径;
lastSpan=检测器。getCurrentSpan();
}
}
}
返回true;
}
}

您看过这个文档了吗:@ditkin我看过那个文档,但我承认我对onScale()版本中很多东西的用途感到困惑。我是否应该使用getCurrentSpan()查找一些要添加到半径的数字?不幸的是,这并没有解决问题,但这可能仍然是一个很好的更改。我可以根据用户做手势的位置限制缩放的时间,但一旦缩放应用,它会立即缩小到很小或很大的比例。好的。我想你需要检查一下你初始化比例手势的位置。检查其初始化与否ScaleGetureDetector在onTouchEvent方法中已初始化。好的,也检查此链接可能会对您有所帮助,谢谢您的帮助!我想出来了,并回答了我自己的问题。使用跨度而不是比例因子是诀窍。您好,您介意发布/发送上面代码片段的完整代码吗?