How to create Gradient Buttons Dynamically without XML in Android?

By | March 10, 2013

Hello all..

I have shown you how to create gradient buttons in Android using XML in this post.

Now I will show you how to create these gradient buttons dynamically.

We will start with a class that extends StateListDrawable similar to state-list we use in XML

UIGradientSelector.java

package com.example.dynamicgradient;

import android.graphics.drawable.StateListDrawable;

/**
 * {@link StateListDrawable} that controls selection of
 * {@link UIGradientDrawable} based on the three basic button states.
 */
public class UIGradientSelector extends StateListDrawable {

	/**
	 * {@link UIGradientSelector} that selects the {@link UIGradientDrawable}
	 * defined by the colors for the three basic button states.
	 * 
	 * @param normalColors
	 *            Array of primitive ints that define the gradient colors for a
	 *            button in its normal state.
	 * @param focusedColors
	 *            Array of primitive ints that define the gradient colors for a
	 *            button in its focused state.
	 * @param pressedColors
	 *            Array of primitive ints that define the gradient colors for a
	 *            button in its pressed state. If the array is null, then
	 *            focusedColors will be used for the pressed state.
	 */
	public UIGradientSelector(int[] normalColors, int[] focusedColors,
			int[] pressedColors) {
		int stateFocused = android.R.attr.state_focused;
		int statePressed = android.R.attr.state_pressed;
		UIGradientDrawable normalGradient = new UIGradientDrawable(normalColors);
		UIGradientDrawable focusedGradient = new UIGradientDrawable(
				focusedColors);
		UIGradientDrawable pressedGradient;

		if (pressedColors == null) {
			pressedGradient = focusedGradient;
		} else {
			pressedGradient = new UIGradientDrawable(pressedColors);
		}

		addState(new int[] { stateFocused }, focusedGradient);
		addState(new int[] { statePressed }, pressedGradient);
		addState(new int[] { -statePressed, -stateFocused }, normalGradient);
	}
}

Now the class that extends PaintDrawable Class.

UIGradientDrawable.java

package com.example.dynamicgradient;

import android.graphics.drawable.PaintDrawable;
import android.graphics.drawable.shapes.RectShape;

/**
 * {@link PaintDrawable} that paints the surface via a {@link UIGradientShader}.
 */
public class UIGradientDrawable extends PaintDrawable {

    /**
     * {@link UIGradientDrawable} with an initial shape of a rounded rectangle
     * that transitions evenly between the specified colors.
     * 
     * @param colors
     *            Array of primitive ints that contain the argb values of the
     *            color to use for transitioning.
     */
    public UIGradientDrawable(int[] colors) {
        UIGradientShader gradientShader = new UIGradientShader(colors);
        setShape(new RectShape());
        setCornerRadius(8);
        setShaderFactory(gradientShader);
        setDither(true);
    }
}

Now the last java class that extends ShaderFactory.
UIGradientShader.java

package com.example.dynamicgradient;

import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable.ShaderFactory;

/**
 * {@link ShaderFactory} that uses a {@link LinearGradient} to transition
 * between specified colors. Any number of colors may be specified.
 */
public class UIGradientShader extends ShaderFactory {
	private int[] colors;
	private float[] positions;

	/**
	 * {@link UIGradientShader} that spaces color transitions evenly across the
	 * painting surface.
	 * 
	 * @param colors
	 *            Array of primitive ints that contain the argb values of the
	 *            color to use for transitioning. If the array contains only one
	 *            color, then an argb of (0, 0, 0, 0) will be used for the end
	 *            color of the transition. If the array is set to null or
	 *            contains zero colors, then the transition will be from an argb
	 *            of (255, 255, 255, 255) to and argb of (0, 0, 0, 0).
	 * 
	 * @see Color
	 */
	public UIGradientShader(int[] colors) {
		init(colors, null);
	}

	/**
	 * {@link UIGradientShader} that spaces color transitions across the
	 * painting surface as specified.
	 * 
	 * @param colors
	 *            Array of primitive ints that contain the argb values of the
	 *            color to use for transitioning. If the array contains only one
	 *            color, then an argb of (0, 0, 0, 0) will be used for the end
	 *            color of the transition. If the array is set to null or
	 *            contains zero colors, then the transition will be from an argb
	 *            of (255, 255, 255, 255) to and argb of (0, 0, 0, 0).
	 * @param positions
	 *            Array of primitive floats that contain the position of the
	 *            transition points. If the array is null, then the color
	 *            transitions will be spaced evenly.
	 */
	public UIGradientShader(int[] colors, float[] positions) {
		init(colors, positions);
	}

	private void init(int[] colors, float[] positions) {
		if (colors == null || colors.length == 0) {
			this.colors = new int[2];
			this.colors[0] = Color.argb(255, 255, 255, 255);
			this.colors[1] = Color.argb(0, 0, 0, 0);
		} else if (colors.length == 1) {
			this.colors = new int[2];
			this.colors[0] = colors[0];
			this.colors[1] = Color.argb(0, 0, 0, 0);
		} else {
			this.colors = colors;
		}

		this.positions = positions;
	}

	public Shader resize(int width, int height) {
		LinearGradient lg = new LinearGradient(0, 0, 0, height, colors,
				positions, Shader.TileMode.REPEAT);
		return lg;
	}

}

Atlast the MainActivity Class that applies these java classes.

package com.example.dynamicgradient;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.Button;
import android.widget.LinearLayout;

public class MainActivity extends Activity {

	protected LinearLayout mainLayout;
	public static Button btn1 = null;
	public static Button btn2 = null;

	// Members
	private int[] normalColors = new int[4];
	private int[] focusedColors = new int[2];
	private int[] disabledColors = new int[1];
	private int defaultSkinR = 255;
	private int defaultSkinG = 100;
	private int defaultSkinB = 150;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		  mainLayout = (LinearLayout) getLayoutInflater().inflate(R.layout.activity_main,
	                null);

	        normalColors[0] = Color.argb(255, defaultSkinR, defaultSkinG,
	                defaultSkinB);
	        normalColors[1] = Color.argb(255, 217, 217, 217);
	        normalColors[2] = Color.argb(191, defaultSkinR, defaultSkinG,
	                defaultSkinB);
	        normalColors[3] = Color.argb(140, defaultSkinR, defaultSkinG,
	                defaultSkinB);

	        focusedColors[0] = Color.argb(100, 242, 242, 242);
	        focusedColors[1] = Color.BLUE;

	        UIGradientSelector gradientSelector1 = new UIGradientSelector(
	                normalColors, focusedColors, null);
	        UIGradientSelector gradientSelector2 = new UIGradientSelector(
	                normalColors, focusedColors, null);

	        disabledColors[0] = Color.argb(153, 216, 216, 216);
	        UIGradientDrawable disabledGradient = new UIGradientDrawable(
	                disabledColors);

	        btn1 = (Button) mainLayout.findViewById(R.id.btn1);
	        btn1.setBackgroundDrawable(gradientSelector1);

	        btn2 = (Button) mainLayout.findViewById(R.id.btn3);
	        btn2.setBackgroundDrawable(disabledGradient);

	        setContentView(mainLayout);
	}

}

Now the Layout XML that contains two buttons.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" 
    android:background="@android:color/black">

    <Button
        android:id="@+id/btn1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:textColor="@android:color/white"
        android:text="Dynamic Gradient Button" />

    <Button
        android:id="@+id/btn3"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:textColor="@android:color/white"
        android:text="Dynamic Gradient Disbled Button" />

</LinearLayout>

Leave a Reply

Your email address will not be published. Required fields are marked *