【问题标题】:How to draw line in different patterns using canvas? [closed]如何使用画布绘制不同图案的线条? [关闭]
【发布时间】:2012-12-22 00:01:25
【问题描述】:

嘿,我想用画布画一条不同图案的线。

任何想法或建议都非常感谢..!!!!

提前致谢。

【问题讨论】:

标签: android android-canvas


【解决方案1】:

我更改了NetCanvas 以绘制一个看起来像您问题中的第二张图片的形状:

public class NetCanvas1 extends View {

    Path path0 = new Path();
    private Paint p0;
    private int points_Num = 20;
    private int first_Points_Num = 5;

    public NetCanvas1(Context context) {
        super(context);
        p0 = new Paint();
        p0.setShader(new LinearGradient(0, 0, 230, getHeight(), Color.GREEN,
                Color.RED, Shader.TileMode.CLAMP));
        p0.setStyle(Style.STROKE);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        float x0 = event.getX();
        float y0 = event.getY();

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            path0.moveTo(x0, y0);
            path0.lineTo(x0, y0);

        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            path0.lineTo(x0, y0);
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            path0.lineTo(x0, y0);
            invalidate();
        }
        return true;
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawPath(path0, p0);
        FlaotPoint[] pointArray = getPoints();
        try {
            for (int i = 0; i < first_Points_Num; i++) {
                for (int j = i; j < pointArray.length; j++) {
                    canvas.drawLine(pointArray[i].getX(), pointArray[i].getY(),
                            pointArray[j].getX(), pointArray[j].getY(), p0);
                }
            }
            path0.reset();
        } catch (Exception e) {
        }
    }

    private FlaotPoint[] getPoints() {
        FlaotPoint[] pointArray = new FlaotPoint[points_Num];
        PathMeasure pm = new PathMeasure(path0, false);
        float length = pm.getLength();
        float distance = 0f;
        float speed = length / points_Num;
        int counter = 0;
        float[] aCoordinates = new float[2];

        while ((distance < length) && (counter < points_Num)) {
            // get point from the path
            pm.getPosTan(distance, aCoordinates, null);
            pointArray[counter] = new FlaotPoint(aCoordinates[0],
                    aCoordinates[1]);
            counter++;
            distance = distance + speed;
        }

        return pointArray;
    }

    class FlaotPoint {
        float x, y;

        public FlaotPoint(float x, float y) {
            this.x = x;
            this.y = y;
        }

        public float getX() {
            return x;
        }

        public float getY() {
            return y;
        }
    }
}

结果取决于points_Numfirst_Points_Num 的值以及与 for 循环中的线连接的点的顺序:

for (int i = 0; i < first_Points_Num; i++) {
                for (int j = i; j < pointArray.length; j++) {
                    canvas.drawLine(pointArray[i].getX(), pointArray[i].getY(),
                            pointArray[j].getX(), pointArray[j].getY(), p0);
                }
            }

您可以更改每个变量的值或点的顺序以更改结果。结果可能如下所示:

我的想法很简单:从路径中获取点并用线连接它们。如果您想了解更多关于从路径中获取点的详细信息,请参阅getPoints() 方法,你可以看到 this answer 和它的引用。我希望这对你有帮助。

【讨论】:

  • 非常好的例子,但运行不顺畅。
  • 嘿,你能建议我如何通过扩展 SurfaceView 来使用相同的代码吗?谢谢。
  • @voidRy 你可以看到this tutorial
【解决方案2】:

你必须使用 Path。文档说:

Path 类封装了复合(多轮廓)几何 由直线段、二次曲线和 三次曲线。 ...

例如,您可以在视图的onTouchEvent(MotionEvent event) 方法中扩展view 并将触摸事件位置添加到path。然后您必须生成与最新触摸事件对应的随机位置并将它们添加到其他实例路径。最后在onDraw()你的视图方法中,画出所有路径。我希望这个sn-p能帮助你理解我的想法:

public class NetCanvas extends View {

    private static final double MAX_DIFF = 15;
    Path path0 = new Path();
    Path path = new Path();
    private Paint p0;
    private Paint p;

    public NetCanvas(Context context) {
        super(context);
        p0 = new Paint();
        p0.setShader(new LinearGradient(0, 0, 230, getHeight(), Color.GREEN,
                Color.RED, Shader.TileMode.CLAMP));
        p0.setStyle(Style.STROKE);

        p = new Paint();
        p.setShader(new LinearGradient(0, 0, 230, getHeight(), Color.BLUE,
                Color.MAGENTA, Shader.TileMode.CLAMP));
        p.setStyle(Style.STROKE);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        float x0 = event.getX();
        float y0 = event.getY();
        float x = generateFloat(event.getX());
        float y = generateFloat(event.getY());

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            path0.moveTo(x0, y0);
            path0.lineTo(x0, y0);

            path.moveTo(x, y);
            path.lineTo(x, y);
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            path0.lineTo(x0, y0);

            path.lineTo(x, y);
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            path0.lineTo(x0, y0);

            path.lineTo(x, y);
        }
        invalidate();
        return true;
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawPath(path0, p0);
        canvas.drawPath(path, p);
    }

    private float generateFloat(Float f){
        double d = (Math.signum(2*Math.random() - 1)) * Math.random() * MAX_DIFF;
        return (float) (f + d);
    }
}

在上面的代码中,我使用了两个paths,但你可以使用三个或更多。同样结果,取决于你在屏幕上的手指速度。例如:

或者它可能看起来像这样:

编辑:

上面的类(NetCanvas)扩展了View,所以你可以创建它的一个实例并使用该实例,就像其他视图一样。例如,你可以简单地将它的一个实例设置为你的Activity的ContentView .这里我重写了onCreate()Activity的方法:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new NetCanvas(this));
    }

虽然您可以更改 NetCanvas 以扩展 SurfaceView 并进行一些其他更改。

【讨论】:

  • @mpp 请查看我的编辑。
  • @mpp 我添加了另一个答案,请查看。希望对您有所帮助。
猜你喜欢
  • 2013-12-21
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
  • 2014-07-19
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 2019-10-23
相关资源
最近更新 更多