Android如何用手指画一条平滑的线

发布于 2021-02-02 22:50:21

http://marakana.com/tutorials/android/2d-graphics-example.html

我在下面使用这个例子。但是,当我在屏幕上移动手指的速度太快时,线条会变成单个点。

我不确定是否可以加快绘图速度。或者,我应该用一条直线连接最后两个点。这两种解决方案中的第二种似乎是一个不错的选择,除了非常快速地移动手指时,您会得到一条较长的直线段,然后是清晰的曲线。

如果还有其他解决方案,那么听听他们的声音会很棒。

感谢您的任何帮助。

关注者
0
被浏览
532
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    正如你提到的,一个简单的解决方案是简单地将点与直线连接起来。这是这样做的代码:

    public void onDraw(Canvas canvas) {
        Path path = new Path();
        boolean first = true;
        for(Point point : points){
            if(first){
                first = false;
                path.moveTo(point.x, point.y);
            }
            else{
                path.lineTo(point.x, point.y);
            }
        }
        canvas.drawPath(path, paint);
    }
    

    确保将油漆从填充更改为描边:

    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(2);
    paint.setColor(Color.WHITE);
    
    

    另一个选择是使用quadTo方法将点与迭代连接:

    public void onDraw(Canvas canvas) {
        Path path = new Path();
        boolean first = true;
        for(int i = 0; i < points.size(); i += 2){
            Point point = points.get(i);
            if(first){
                first = false;
                path.moveTo(point.x, point.y);
            }
    
            else if(i < points.size() - 1){
                Point next = points.get(i + 1);
                path.quadTo(point.x, point.y, next.x, next.y);
            }
            else{
                path.lineTo(point.x, point.y);
            }
        }
    
        canvas.drawPath(path, paint);
    }
    

    这仍然会导致一些尖锐的边缘。

    如果你确实有野心,则可以开始如下计算三次样条:

    public void onDraw(Canvas canvas) {
        Path path = new Path();
    
        if(points.size() > 1){
            for(int i = points.size() - 2; i < points.size(); i++){
                if(i >= 0){
                    Point point = points.get(i);
    
                    if(i == 0){
                        Point next = points.get(i + 1);
                        point.dx = ((next.x - point.x) / 3);
                        point.dy = ((next.y - point.y) / 3);
                    }
                    else if(i == points.size() - 1){
                        Point prev = points.get(i - 1);
                        point.dx = ((point.x - prev.x) / 3);
                        point.dy = ((point.y - prev.y) / 3);
                    }
                    else{
                        Point next = points.get(i + 1);
                        Point prev = points.get(i - 1);
                        point.dx = ((next.x - prev.x) / 3);
                        point.dy = ((next.y - prev.y) / 3);
                    }
                }
            }
        }
    
        boolean first = true;
        for(int i = 0; i < points.size(); i++){
            Point point = points.get(i);
            if(first){
                first = false;
                path.moveTo(point.x, point.y);
            }
            else{
                Point prev = points.get(i - 1);
                path.cubicTo(prev.x + prev.dx, prev.y + prev.dy, point.x - point.dx, point.y - point.dy, point.x, point.y);
            }
        }
        canvas.drawPath(path, paint);
    }
    

    另外,我发现你需要更改以下内容以避免重复的运动事件:

    public boolean onTouch(View view, MotionEvent event) {
        if(event.getAction() != MotionEvent.ACTION_UP){
            Point point = new Point();
            point.x = event.getX();
            point.y = event.getY();
            points.add(point);
            invalidate();
            Log.d(TAG, "point: " + point);
            return true;
        }
        return super.onTouchEvent(event);
    }
    
    

    并将dx和dy值添加到Point类:

    class Point {
        float x, y;
        float dx, dy;
    
        @Override
        public String toString() {
            return x + ", " + y;
        }
    }
    

    这样可以产生平滑的线条,但有时必须使用循环将点连接起来。另外,对于较长的绘图会话,这将需要大量计算才能计算。

    希望对你有所帮助。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看