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 > |