Phenome
Phenome

Reputation: 893

Changing gradient background colors on Android at runtime

I'm experimenting with Drawable backgrounds and have had no problems so far.

I'm now trying to change the gradient background color at runtime.

Unfortunately, there's no API to change it at runtime, it seems. Not even by trying to mutate() the drawable, as explained here: Drawable mutations

The sample XML looks like this. It works, as expected.

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:startColor="#330000FF"
        android:endColor="#110000FF"
        android:angle="90"/>
</shape>

Sadly, I want a list with various colors, and they'd have to be programatically altered at runtime.

Is there another way to create this gradient background at runtime? Perhaps even not using XML altogether?

Upvotes: 29

Views: 37679

Answers (5)

Rajesh.k
Rajesh.k

Reputation: 2437

Try my code below:

int[] colors = new int[2];
colors[0] = getRandomColor();
colors[1] = getRandomColor();

GradientDrawable gd = new GradientDrawable(
    GradientDrawable.Orientation.TOP_BOTTOM, colors
);

gd.setGradientType(GradientDrawable.RADIAL_GRADIENT);
gd.setGradientRadius(300f);
gd.setCornerRadius(0f);
 
YourView.setBackground(gd);

Method for generating random color:

public static int getRandomColor(){
    Random rnd = new Random();
    return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
}

Upvotes: 9

Dhananjay M
Dhananjay M

Reputation: 1861

Kotlin version of the answer provided by Phenome as an extension function:

fun View.backgroundGradientDrawable(@ColorInt startColor: Int, @ColorInt endColor: Int): Unit {
    val h = this.height.toFloat()
    val shapeDrawable = ShapeDrawable(RectShape())
    shapeDrawable.paint.shader =
        LinearGradient(0f, 0f, 0f, h, startColor, endColor, Shader.TileMode.REPEAT)
    this.background = shapeDrawable
}

Github

Upvotes: 1

Yogesh
Yogesh

Reputation: 311

I tried using Phenome's solution for Button view. But somehow it did not work.

I came up with something else: (Courtesy: Android API Demo examples)

package com.example.testApp;

import android.app.Activity;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.view.View;

public class TetApp extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        View v = findViewById(R.id.btn);
        v.setBackgroundDrawable( new DrawableGradient(new int[] { 0xff666666, 0xff111111, 0xffffffff }, 0).SetTransparency(10));

    }

    public class DrawableGradient extends GradientDrawable {
        DrawableGradient(int[] colors, int cornerRadius) {
            super(GradientDrawable.Orientation.TOP_BOTTOM, colors);

            try {
                this.setShape(GradientDrawable.RECTANGLE);
                this.setGradientType(GradientDrawable.LINEAR_GRADIENT);
                this.setCornerRadius(cornerRadius);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public DrawableGradient SetTransparency(int transparencyPercent) {
            this.setAlpha(255 - ((255 * transparencyPercent) / 100));

            return this;
        }
    }
}

Upvotes: 12

Phenome
Phenome

Reputation: 893

Yes! Found a way!

Had to forget about XML, but here's how I did it:

On my getView() overloaded function (ListAdapter) I just had to:

    int h = v.getHeight();
    ShapeDrawable mDrawable = new ShapeDrawable(new RectShape());
    mDrawable.getPaint().setShader(new LinearGradient(0, 0, 0, h, Color.parseColor("#330000FF"), Color.parseColor("#110000FF"), Shader.TileMode.REPEAT));
    v.setBackgroundDrawable(mDrawable);

And that gave me the same result as the XML background above. Now I can programmatically set the background color.

Upvotes: 47

Ted Hopp
Ted Hopp

Reputation: 234857

Depending on your requirements, using a color state list instead of a fixed color for startColor and endColor might do what you want.

Upvotes: 0

Related Questions