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>