如何在android Canvas上绘制实心三角形

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20544668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:01:03  来源:igfitidea点击:

How to draw filled triangle on android Canvas

androidandroid-canvasshape

提问by Egis

I have class MyView that extends View class. MyView should draw filled triangle. I drew a triangle but I cannot get it filled. This is my onDraw() method:

我有扩展 View 类的 MyView 类。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);
}

This is what I get as a result:

这就是我得到的结果:

enter image description here

在此处输入图片说明

回答by Egis

I've found the answer

我找到了答案

@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);
}

回答by Joe Maher

This answer provides a bit of clarity on where the numbers given in the answer by @Egis come from. (this will draw an upside down equilateral triangle and is written in kotlin)

这个答案对@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
    }
}

The get height function is Pythagoras' Theoremand will always find the height of an equilateral triangle to be ~87% of its side length

获取高度函数是毕达哥拉斯定理,并且总是会发现等边三角形的高度是其边长的 87%

Gistcan be found here, it contains code for the other direction

要点可以在这里找到,它包含另一个方向的代码

回答by Jarvis

I recently created a small demo app drawing various shapes, including triangles, rectangles and spirals. Here is the code for drawing the triangles. For full context, reference the project. In this app, the user can draw a triangle as a single drawing or a composition of two triangles forming into one as the user scrolls. The increasing triangle growth is accomplished through the principles of Triangle Similarity, with each smaller triangle similar to the large triangle in the end.

我最近创建了一个小型演示应用程序,可以绘制各种形状,包括三角形、矩形和螺旋形。这是绘制三角形的代码。有关完整上下文,请参考该项目。在此应用程序中,用户可以将一个三角形绘制为单个图形,也可以在用户滚动时将两个三角形组合成一个。三角形的增长是通过三角形相似的原则来实现的,每个小三角形最终都与大三角形相似。

Project: https://github.com/jdgreene2008/android_custom_views

项目:https: //github.com/jdgreene2008/android_custom_views

Source Excerpt: https://github.com/jdgreene2008/android_custom_views/blob/master/CustomUiComponents/app/src/main/java/com/jarvis/dragdropresearch/views/FlashShapeView.java

源代码摘录: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);
        }
    }

回答by Bismeet Singh

I would like to point out that you should never initiialize an object from onDraw() as it gets called multiple times and leads to performance problems.

我想指出的是,永远不要从 onDraw() 初始化对象,因为它会被多次调用并导致性能问题。