29

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?

Phenome
  • 894
  • 1
  • 7
  • 12

5 Answers5

47

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.

Phenome
  • 894
  • 1
  • 7
  • 12
12

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;
        }
    }
}
Yogesh
  • 311
  • 1
  • 10
9

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(56), rnd.nextInt(256));
}
Rajesh.k
  • 2,327
  • 1
  • 16
  • 19
1

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

Dhananjay M
  • 1,851
  • 22
  • 18
0

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

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • Interesting alternative, but I really need something more dynamic. It's a list that shows information from different pluggable providers. Each provider has a custom color, so the user knows where that information is from. I know that isn't much information, but perhaps it will help. – Phenome Feb 09 '11 at 09:21