【问题标题】:How to draw filled triangle on android Canvas如何在 android Canvas 上绘制实心三角形
【发布时间】:2013-12-12 13:19:30
【问题描述】:

我有扩展 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);
}

这是我得到的结果:

【问题讨论】:

    标签: android android-canvas shape


    【解决方案1】:

    我找到了答案

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

    【讨论】:

    • 第一行应该是 moveTo。否则它将从点 (0, 0) 开始绘制。在这种情况下不是问题,但我遇到了它,因为我想从中心绘制。
    • Android 建议不要在 onDraw() 中进行对象分配,现在 IDE 会自动发出警告。但是,请记住在canvas.drawPath() 之后调用path.reset()
    【解决方案2】:

    这个答案清楚地说明了@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
        }
    }
    

    get height 函数是Pythagoras' Theorem,它总是会发现等边三角形的高度约为其边长的 87%

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

    【讨论】:

      【解决方案3】:

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

      项目: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);
              }
          }
      

      【讨论】:

        【解决方案4】:
        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-30
          • 1970-01-01
          • 1970-01-01
          • 2021-10-31
          • 2021-08-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多