如何在Android画布上绘制填充三角形

23

我有一个类MyView,它继承自View类。MyView应该画一个填充的三角形。我已经画了一个三角形,但我无法使它填充。这是我的onDraw()方法:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint paint = new Paint();

    paint.setColor(android.graphics.Color.BLACK);
    canvas.drawPaint(paint);

    paint.setStrokeWidth(4);
    paint.setColor(android.graphics.Color.RED);
    paint.setStyle(Paint.Style.FILL_AND_STROKE);
    paint.setAntiAlias(true);

    Point a = new Point(0, 0);
    Point b = new Point(0, 100);
    Point c = new Point(87, 50);

    Path path = new Path();
    path.setFillType(FillType.EVEN_ODD);
    path.moveTo(a.x, a.y);
    path.lineTo(b.x, b.y);
    path.moveTo(b.x, b.y);
    path.lineTo(c.x, c.y);
    path.moveTo(c.x, c.y);
    path.lineTo(a.x, a.y);
    path.close();

    canvas.drawPath(path, paint);
}

这是我得到的结果:

在此输入图片描述

5个回答

29

我已经找到答案

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint paint = new Paint();

    paint.setColor(android.graphics.Color.BLACK);
    canvas.drawPaint(paint);

    paint.setStrokeWidth(4);
    paint.setColor(android.graphics.Color.RED);
    paint.setStyle(Paint.Style.FILL_AND_STROKE);
    paint.setAntiAlias(true);

    Point a = new Point(0, 0);
    Point b = new Point(0, 100);
    Point c = new Point(87, 50);

    Path path = new Path();
    path.setFillType(FillType.EVEN_ODD);
    path.lineTo(b.x, b.y);
    path.lineTo(c.x, c.y);
    path.lineTo(a.x, a.y);
    path.close();

    canvas.drawPath(path, paint);
}

11
第一条线应该改为移动到(moveTo),否则它将从点(0,0)开始绘制。虽然在这种情况下不是问题,但我想从中心开始绘制时遇到了这个问题。 - lucasjmatias
1
Android建议不要在onDraw()中进行对象分配,这在IDE中现在会自动警告。但是,请记得在canvas.drawPath()之后调用path.reset() - Sira Lam

1
这篇答案为@Egis的回答中给出的数字来源提供了一些澄清。 (这将绘制一个倒置的等边三角形,并用kotlin编写)
class TriangleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {

    val paint = Paint()
    val path = Path()

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        canvas ?: return
        canvas.drawPath(configurePath(canvas.width.toFloat(), path), configurePaint(paint))
    }

    fun getHeight(width: Double): Float {
        return Math.sqrt((Math.pow(width, 2.0) - Math.pow((width / 2), 2.0))).toFloat()
    }

    fun configurePaint(paint: Paint): Paint {
        paint.color = android.graphics.Color.WHITE
        paint.isAntiAlias = true

        return paint
    }

    fun configurePath(width: Float, path: Path): Path {
        path.lineTo((width / 2f), getHeight(width.toDouble()))
        path.lineTo(width, 0F)
        path.lineTo(0f, 0f)

        return path
    }
}

获取高度的函数是勾股定理,它总能找到等边三角形的高度为其边长的~87%

Gist可以在这里找到,其中包含了另一方向的代码


1
我最近创建了一个小型演示应用程序,绘制各种形状,包括三角形、矩形和螺旋线。以下是绘制三角形的代码。要获取完整上下文,请参考该项目。在此应用程序中,用户可以将三角形作为单个图形或两个三角形组成的合成图形进行绘制,并随着用户滚动而逐渐增大。通过三角形相似原理实现三角形的增长,每个较小的三角形与最终的大三角形相似。
项目: https://github.com/jdgreene2008/android_custom_views 源码摘录: https://github.com/jdgreene2008/android_custom_views/blob/master/CustomUiComponents/app/src/main/java/com/jarvis/dragdropresearch/views/FlashShapeView.java
 private void drawTriangleShape(Canvas canvas, RectF bounds,
            TriangleInterpolator triangleInterpolator, Paint paint) {
        paint.setStyle(Paint.Style.FILL);

        float baseInterpolation = triangleInterpolator
                .getInterpolatedValues()[TriangleInterpolator.INTERPOLATION_VALUES_BASE];
        float altitudeInterpolation = triangleInterpolator
                .getInterpolatedValues()[TriangleInterpolator.INTERPOLATION_VALUES_ALTITUDE];

        // *** Construct the Left Triangle ** //

        // Bottom left vertex
        float bottomLeftX = bounds.left;
        float bottomLeftY = bounds.bottom;

        // Bottom right corner
        float bottomRightX = bottomLeftX + baseInterpolation;
        float bottomRightY = bounds.bottom;

        //Top Vertex
        float topX = bottomRightX;
        float topY = bottomRightY - altitudeInterpolation;

        Path leftTriangle = new Path();
        leftTriangle.lineTo(bottomLeftX, bottomLeftY);
        leftTriangle.lineTo(bottomRightX, bottomRightY);
        leftTriangle.lineTo(topX, topY);
        leftTriangle.lineTo(bottomLeftX, bottomLeftY);

        canvas.drawPath(leftTriangle, paint);

        if (triangleInterpolator.isSymmetric()) {
            // *** Construct the Right Triangle ** //

            bottomLeftX = bounds.right - baseInterpolation;
            bottomLeftY = bounds.bottom;

            bottomRightX = bounds.right;
            bottomRightY = bounds.bottom;

            topX = bottomLeftX;
            topY = bottomRightY - altitudeInterpolation;

            Path rightTriangle = new Path();
            rightTriangle.lineTo(bottomLeftX, bottomLeftY);
            rightTriangle.lineTo(bottomRightX, bottomRightY);
            rightTriangle.lineTo(topX, topY);
            rightTriangle.lineTo(bottomLeftX, bottomLeftY);

            canvas.drawPath(rightTriangle, paint);
        }
    }


0
我想指出的是,您不应该在onDraw()中初始化对象,因为它会被多次调用,从而导致性能问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接