4

I want to create a CircleView with gradient from bottom -> left -> top -> right.
So I using canvas with SweepGradient like this

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint paint = new Paint();

    int[] colors = {Color.GREEN, Color.RED};
    float[] positions = {0, 1};

    SweepGradient gradient = new SweepGradient(100, 100, colors, positions);
    paint.setShader(gradient);
    canvas.drawCircle(100, 100, 100, paint);
}

enter image description here

But the default order of this is right -> bottom -> left -> top but I want bottom -> left -> top -> right I have tried change the positions to

float[] positions = {0.25f, 1.25f};

but it only works in Preview of AndroidStudio, when I run in real device, it displays the result as same as positions = {0, 1}

How can I make SweepGradient gradient from bottom -> left -> top -> right like this

enter image description here

--- UPDATE --- We can use setLocalMatrix for SweepGradient like this for rotate the gradient

Matrix matrix = new Matrix();
matrix.setRotate(90, 100, 100);
gradient.setLocalMatrix(matrix);

enter image description here

Linh
  • 57,942
  • 23
  • 262
  • 279

1 Answers1

6

Rotate the canvas before drawing the circle.

public class CircleView extends View {
    private Paint paint;

    public CircleView(Context context) {
        super(context);
        init();
    }

    public CircleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public void init() {
        paint = new Paint();

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

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.rotate(90, 100, 100);
        canvas.drawCircle(100, 100, 100, paint);
        canvas.restore();
    }
}

Edit-1:
Alternative approach suggested by @pkskink is to use setLocalMatrix like below:

public void init() {      
    int[] colors = {Color.GREEN, Color.RED};
    float[] positions = {0, 1};

    Matrix matrix = new Matrix();
    matrix.postRotate(90, 100, 100);

    Shader gradient = new SweepGradient(100, 100, colors, positions);
    gradient.setLocalMatrix(matrix);

    paint = new Paint();
    paint.setShader(gradient);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawCircle(100, 100, 100, paint);
}
Community
  • 1
  • 1
blizzard
  • 5,275
  • 2
  • 34
  • 48
  • Do you know another way to do it without rotate the canvas. In my project now, after I create `SweepGradient` I need to set it as background an ARC seekbar (https://github.com/neild001/SeekArc). For circle we can rotate, but for ARC seekbar we can not rotate – Linh Nov 27 '16 at 12:33
  • Sorry @PhanVanLinh I don't know other way, but Please create a separate post for the above question. – blizzard Nov 27 '16 at 13:05