【问题标题】:Android add line markers to edges of arcAndroid将线标记添加到弧的边缘
【发布时间】:2019-08-23 20:02:11
【问题描述】:

我们如何在arc 的边缘添加line 标记。

我们知道arc 可以使用以下方法绘制:

canvas.drawArc(arcBounds, 0, 90, false, paint);

以上语句将在下午 3 点到 6 点绘制arc。我想在arc 的两个边缘添加line 标记,如下图所示。

我可以使用以下方法在两个边缘画圆:

canvas.drawCircle(endX, endY, 5, timeArcPaints);

我有arcstartXstartYendXendY 位置,但是我不确定如何绘制line 标记以使其处于相同的角度作为arc 端点。

public void drawLine (float startX, 
                float startY, 
                float stopX, 
                float stopY, 
                Paint paint)

谢谢!

【问题讨论】:

    标签: java android math android-canvas wear-os


    【解决方案1】:

    自定义视图代码

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.view.View;
    
    public class MarkerView extends View {
    
        private final Paint markerPaint;
        private RectF oval;
        private final int boundingRectDimens = 200;
        private int centerX;
        private int centerY;
    
        private final float startAngle = 190;
        private final float sweepAngle = 90;
        private final float markerAngle = 180; // angle of markers w.r.t start point and end/sweep point
    
    
        public MarkerView(Context context) {
            super(context);
            markerPaint = createMarkerPaint();
    
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            centerX = w / 2;
            centerY = h / 2;
            oval = new RectF(centerX - boundingRectDimens,
                    centerY - boundingRectDimens,
                    centerX + boundingRectDimens,
                    centerY + boundingRectDimens);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawColor(Color.DKGRAY);
            canvas.drawArc(oval, startAngle, sweepAngle, false, markerPaint);
    
    
            float startX, startY, endX, endY;
            // calculate start points.
    
            //get a line from startAngle till markerAngle.
            startX = (float) (Math.cos(Math.toRadians(startAngle)) * boundingRectDimens + centerX);
            startY = (float) (Math.sin(Math.toRadians(startAngle)) * boundingRectDimens + centerY);
            endX = (float) (Math.cos(Math.toRadians(startAngle + markerAngle)) * boundingRectDimens + centerX);
            endY = (float) (Math.sin(Math.toRadians(startAngle + markerAngle)) * boundingRectDimens + centerY);
    
            // we need to draw only a part of the entire line, using vector for this.
            // vector dimens.
            float desiredLen = 0.05f;  // maker height can be adjusted by changing this value.
            float upLen = 1 - desiredLen;
            float downLen = 1 + desiredLen;
            // calculate down vector.
            float desiredX = downLen * (startX - endX) + endX;
            float desiredY = downLen * (startY - endY) + endY;
    
            markerPaint.setColor(Color.YELLOW);
            canvas.drawLine(startX, startY, desiredX, desiredY, markerPaint);
            // get up vector
            desiredX = upLen * (startX - endX) + endX;
            desiredY = upLen * (startY - endY) + endY;
            canvas.drawLine(startX, startY, desiredX, desiredY, markerPaint);
    
    
            // repeat same for end/sweep point.
            startX = (float) (Math.cos(Math.toRadians(startAngle + sweepAngle)) * boundingRectDimens + centerX);
            startY = (float) (Math.sin(Math.toRadians(startAngle + sweepAngle)) * boundingRectDimens + centerY);
            endX = (float) (Math.cos(Math.toRadians(startAngle + sweepAngle + markerAngle)) * boundingRectDimens + centerX);
            endY = (float) (Math.sin(Math.toRadians(startAngle + sweepAngle + markerAngle)) * boundingRectDimens + centerY);
    
            // calculate down vector.
            desiredX = downLen * (startX - endX) + endX;
            desiredY = downLen * (startY - endY) + endY;
    
            markerPaint.setColor(Color.BLUE);
            canvas.drawLine(startX, startY, desiredX, desiredY, markerPaint);
            // get up vector
            desiredX = upLen * (startX - endX) + endX;
            desiredY = upLen * (startY - endY) + endY;
            canvas.drawLine(startX, startY, desiredX, desiredY, markerPaint);
    
    
        }
    
    
        private Paint createMarkerPaint() {
            Paint p = new Paint();
            p.setAntiAlias(true);
            p.setDither(true);
            p.setColor(Color.RED);
            p.setStyle(Paint.Style.STROKE);
            p.setStrokeWidth(20);
            p.setStrokeCap(Paint.Cap.ROUND); // makes the stroke projects out as semicircle
            p.setStrokeJoin(Paint.Join.ROUND); // makes outer edges of a join meet in circular arc
            return p;
        }
    }
    

    【讨论】:

    • markerAngle 是什么?可以根据用户输入以任意角度绘制圆弧,那么如何确保 markerAngle 有效?
    • Markerangle 是标记与要绘制标记的圆弧点之间的角度。它在 165 到 195 的范围内看起来不错,您可以使用不同的值并决定自己的最佳值。
    • 如果你想要简单的标记,保持标记角度为 180
    • 嗯,我一定是做错了什么。这两个标记显示在圆的中心而不是弧的末端。我认为这是因为 boundingDimens 已被硬编码。
    • 我会赞成这个答案,因为这是朝着正确方向迈出的一步。如果你能帮忙找出在此期间会很棒的 boundingDimens。
    【解决方案2】:

    在android中,paint包含如何绘制视图的样式和颜色信息。您需要使用paint Style来实现您想要的绘图。

    为标记创建油漆

     private Paint createMarkerPaint(){
        Paint p = new Paint();
        p.setAntiAlias(true);
        p.setDither(true);
        p.setColor(Color.RED);
        p.setStyle(Paint.Style.FILL_AND_STROKE);
        p.setStrokeWidth(20);
        p.setStrokeCap(Paint.Cap.ROUND); // makes the stroke projects out as semicircle
        p.setStrokeJoin(Paint.Join.ROUND); // makes outer edges of a join meet in circular arc
        return p;
    }
    

    使用此函数创建线标记

     private void drawLineMarkers(Canvas c, float startX, float startY, float endX, float endY){
    
        int lineHeight = 20; // play with it
        int lineWidth = 20; // play with it
        c.drawLine(startX, startY, startX - lineWidth, startY - lineHeight, markerPaint);
        c.drawLine(startX, startY, startX + lineWidth, startY + lineHeight, markerPaint);
    
        c.drawLine(endX, endY, endX - lineWidth, endY - lineHeight, markerPaint);
        c.drawLine(endX, endY, endX + lineWidth, endY + lineHeight, markerPaint);
    
    }
    

    【讨论】:

    • 对不起。我的问题是如何在适当的平面上找到画线。
    • 你想知道如何计算drawLineMarkers()中使用的点(startX, startY, endX, endY)吗?
    • 是的。还有我们如何在那个平面上画线。
    • 我已经实现了解决方案,但是由于实验它不干净,我会清理它,添加支持文档并明天发布答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    相关资源
    最近更新 更多