web-dev-qa-db-ja.com

Android-円弧ベースのグラデーションを描画する方法

ある色から別の色に徐々に変化する円弧(度数が可変)を作成しようとしています。青から赤への例から:

enter image description here

これは私のコードです:

SweepGradient shader = new SweepGradient(center.x, center.y, resources.getColor(R.color.startColor),resources.getColor(R.color.endColor));
Paint paint = new Paint()
Paint.setStrokeWidth(1);
Paint.setStrokeCap(Paint.Cap.FILL);
Paint.setStyle(Paint.Style.FILL);
Paint.setShader(shader);
canvas.drawArc(rectF, startAngle, sweepAngle, true, Paint);

しかし、その結果、アーク全体が同じ色でペイントされます。

編集:
さらに実験を重ねた結果、色の広がりは円弧の角度によって決まることがわかりました。小さな角度で円弧を描くと、最初の色だけが表示されます。角度が大きいほど、より多くの色が描画されます。角度が小さければ勾配がないようです。
これが例です。私は4つの弧を描いています-90、180、270、360:

RectF rect1 = new RectF(50, 50, 150, 150);
Paint paint1 = new Paint();
Paint1.setStrokeWidth(1);
Paint1.setStrokeCap(Paint.Cap.SQUARE);
Paint1.setStyle(Paint.Style.FILL);

SweepGradient gradient1 = new SweepGradient(100, 100,
        Color.RED, Color.BLUE);
Paint1.setShader(gradient1);

canvas.drawArc(rect1, 0, 90, true, Paint1);

RectF rect2 = new RectF(200, 50, 300, 150);
Paint paint2 = new Paint();
Paint2.setStrokeWidth(1);
Paint2.setStrokeCap(Paint.Cap.SQUARE);
Paint2.setStyle(Paint.Style.FILL);

SweepGradient gradient2 = new SweepGradient(250, 100,
        Color.RED, Color.BLUE);
Paint2.setShader(gradient2);

canvas.drawArc(rect2, 0, 180, true, Paint2);

RectF rect3 = new RectF(50, 200, 150, 300);
Paint paint3 = new Paint();
Paint3.setStrokeWidth(1);
Paint3.setStrokeCap(Paint.Cap.SQUARE);
Paint3.setStyle(Paint.Style.FILL);

SweepGradient gradient3 = new SweepGradient(100, 250,
        Color.RED, Color.BLUE);
Paint3.setShader(gradient3);

canvas.drawArc(rect3, 0, 270, true, Paint3);

RectF rect4 = new RectF(200, 200, 300, 300);
Paint paint4 = new Paint();
Paint4.setStrokeWidth(1);
Paint4.setStrokeCap(Paint.Cap.SQUARE);
Paint4.setStyle(Paint.Style.FILL);

SweepGradient gradient4 = new SweepGradient(250, 250,
        Color.RED, Color.BLUE);
Paint4.setShader(gradient4);

canvas.drawArc(rect4, 0, 360, true, Paint4);

そしてここに結果があります:

enter image description here

これは驚くべきことです。なぜなら、赤は弧の始点にあり、青は弧の終点にあり、その間のすべてが角度に関係なく均等に広がることを期待しているからです。
positionsパラメータを使用して手動で色の間隔を空けようとしましたが、結果は同じでした。

int[] colors = {Color.RED, Color.BLUE};
float[] positions = {0,1};
SweepGradient gradient = new SweepGradient(100, 100, colors , positions);

これを解決する方法はありますか?

23
Yoav

これに対する解決策は、BLUEの位置を設定することです。これは次のように行われます。

int[] colors = {Color.RED, Color.BLUE};
float[] positions = {0,1};
SweepGradient gradient = new SweepGradient(100, 100, colors , positions);

ここでの問題は、BLUEの位置を「1」に設定する場合、これは描画された円弧の端に配置されることを意味するのではなく、円弧が含まれる円の端に配置されることを意味します。これを解決するには、青の位置で円弧の度数を考慮する必要があります。したがって、X度の円弧を描く場合、位置は次のように設定されます。

float[] positions = {0,Xf/360f};

したがって、Xが90の場合、グラデーションは円の0.25に青を配置します。

enter image description here

30
Yoav

Yoavのソリューションに追加します。

私のGalaxyNexus 4.2ストックAndroidでは、与えられたソリューションは機能しません。

配列に0.0fと1.0fが含まれていない場合、無視されているように見えます。

私の最終的な解決策は次のとおりです。

int[] colors = {Color.RED, Color.BLUE, Color.RED}; 
float[] positions = {0, Xf/360f, 1};
11
Tom anMoney

5年後ですが、正しい方法は、0.749fを0.750fの別行で作成することです。単純なコードは、次のようになります。

    val colors = intArrayOf(0xffff0000.toInt(), 0xff0000ff.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt())
    val positions = floatArrayOf(0.0f, 0.749f, 0.750f, 1.0f)
1
zmj110