【问题标题】:SweepGradient Android - How to set start angle for GradientSweepGradient Android - 如何设置渐变的起始角度
【发布时间】:2020-02-14 19:42:15
【问题描述】:

我很难理解如何使用SweepGradientCanvas 的特定角度显示我的渐变色。

例如:如果我有一个从下午 1 点到下午 3 点的弧,我想提供一个Gradient 作为ColorGradient 应该从下午 2 点开始。

我有以下代码显示Color 没有应用任何渐变。

 SweepGradient sweepGradient = new
                                SweepGradient(provideRectF().width() / 2, provideRectF().height() / 2,
                                arcColors, new float[]{
                                0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f
                        });

                        Matrix matrix = new Matrix();
                        matrix.postRotate(currentAngle, provideRectF().width() / 2, provideRectF().height() / 2);
                        sweepGradient.setLocalMatrix(matrix);

如何让我的Color 显示给定弧线从下午 2 点开始的渐变(以角度表示)?

【问题讨论】:

    标签: android android-canvas gradient ondraw


    【解决方案1】:

    此答案基于 Attila Tanyi 的 excellent post on SweepGradient

    为了更好地理解SweepGradient,让我们首先用SweepGradient 绘制整个屏幕,该SweepGradient 位于屏幕中间并显示与钟面相对应的部分(请注意下午1 点到下午1 点之间的区域)下午 2 点是纯色,因为这是您设置的一部分):

    职位:

    // positions for a clock face
    // note: we need an opening position 0.0f as well as a closing position 1.0f, both of which belong to 3 pm
    float[] positions = {0.0f,
                1/12f, 2/12f, 3/12f, 
                4/12f, 5/12f, 6/12f,
                7/12f, 8/12f, 9/12f,
                10/12f, 11/12f, 1.0f};
    

    颜色:

    int yellow = 0xFFFFFF88;
    int blue = 0xFF0088FF;
    int white = 0xFFFFFFFF;
    int black = 0xFF000000;
    
    // provide as many color values as there are positions
    // we want to paint a "normal color" from 1pm to 2pm and then a gradient from 2pm to 3 pm
    int[] colors = { black, // the first value is for 3 pm, the sweep starts here
            yellow, // 4
            white,  // 5
            black,  // 6
            white,  // 7
            yellow, // 8
            blue,   // 9
            black,  // 10
            white,  // 11
            black,  // 12
            blue,   // 1 constant color from 1pm to 2pm
            blue,   // 2
            white // the last value also is at 3 pm, the sweep ends here
    };
    

    初始化PathPaint

    private Path circle = new Path();
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    
    // ...
    paint.setStyle(Paint.Style.FILL_AND_STROKE);
    paint.setStrokeWidth(30);
    

    我尝试了自定义View,并在onLayout() 中配置了渐变。由于帖子是关于画圆弧的,接下来我尝试了一个完整的圆:

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        // use a square rectangle which does not touch the screen borders:
        float squareMaxWidth = Math.min(right - left, bottom - top) - 20;
        RectF circleRect = new RectF(left + 20, top + 20, left + squareMaxWidth, top + squareMaxWidth);
        // draw a full circle
        circle.addArc(circleRect, 180, 360);
        // calculate its center
        float centerH = (circleRect.right + circleRect.left)*0.5f;
        float centerV = (circleRect.bottom + circleRect.top)*0.5f;
    
        sweepGradient = new SweepGradient(centerH,centerV, colors, positions);
        paint.setShader(sweepGradient);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(circle, paint);
    }
    

    结果:

    接下来,我们只画边框:更改Paint 样式

    paint.setStyle(Paint.Style.STROKE);
    

    最后,从下午 1 点到下午 3 点画一条弧线。请记住,下午 3 点的角度为零,而钟面上的一个部分对应于 30 度。所以在onLayout()我们有

    circle.addArc(circleRect, 300, 60);
    

    另一个例子:如果你想从下午 4:15 到 4:45 绘制一条弧线,从下午 4:33 开始渐变,你会得到下面的图片(彩色弧线绘制在一个完整的 SweepGradient 圆上在每个“小时”交替黑白)

    颜色:

    int[] colors = {      
            primaryColor,
            primaryColor,
            accentColor };
    

    要计算位置,需要做一些数学运算:

    60 分钟 = 一小时 ~ 1/12f
    3 分钟 = 1 小时 / 20 ~ 1/240f
    15 分钟 = 5 * 3 分钟 ~ 5 / 240f = 1 / 48f
    45 分钟 = 3 * 15 分钟 ~ 1 / 16f
    33 分钟 = 11 * 3 分钟 ~ 11 / 240f

    float[] positions = {
            (1/12f + 1/48f),   // 4:15 pm
            (1/12f + 11/240f), // 4:33 pm
            (1/12f + 1/16f)    // 4:45 pm
         };
    

    同样,可以计算起始角和后掠角的值:

    一小时~30度
    一分钟 ~ 0.5 度

    // start at 4:15 pm:
    float startAngle = (30 +  15*0.5f);
    // sweep for 1/2 hour:
    float sweepAngle = 15f;
    circle.addArc(circleRect, startAngle, sweepAngle);
    

    【讨论】:

    • 非常感谢您这么详细的回答!位置数组的目的是什么?这似乎让我最困惑。
    • @user2511882 - 让我感到困惑的是,角度是以度数(0 到 360)来衡量的,但是对于查看完整弧线的位置(从下午 3 点顺时针到下午 3 点)并认为它是“一条完整的路径”(又名 100% 或 1.0f)各个位置类似于百分比值:0.1f 表示路径长度的 10%。你需要一个钟面,所以我使用了分母为 12 的分数
    • 知道了。所以我说颜色数组代表从 0 度(即下午 3 点)开始的每个位置是否正确?
    • @user2511882 - 是的,每个位置都需要一种颜色。 SweepGradient 就像是两种颜色之间的一系列过渡
    • @user2511882 - 由于您只对下午 1 点到 3 点之间的弧线感兴趣,因此您可以省略大部分位置。这也应该起作用: int[] colors = {white, yellow, blue, blue, blue, white };浮动[] 位置 = {0.0f, 1/12f, 9/12f, 10/12f, 11/12f, 1.0f};
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 2011-01-28
    • 2021-12-21
    • 2018-04-17
    相关资源
    最近更新 更多