An efficient way to change the background color of Android buttons

Source: Internet
Author: User
Tags getcolor home screen

This article describes a way to effectively change the color of the Android button.

The button can change its color when the state changes (for example, press, disable, highlight). However, this requires one by one to describe each state. This article will provide you with a way to easily change the color of the button depending on the state change. If you're writing a custom view, you might as well read it, because in the middle I'll refer to how to implement custom views with custom attributes.

How to achieve

Android provides a flexible drawing selection mechanism to transform the view appearance based on view state. Each state exists through a separate section. For example, buttons with a normal, disabled, pressed, highlighted color have different background colors. Take a look at the following code example:

Button_1_background.xml

<selector xmlns:android= "Http://schemas.android.com/apk/res/android" ><!&mdash; Pressed state--><item android:drawable= "@drawable/button_1_selected" android:state_pressed= "true"/><! --focused state--><item android:drawable= "@drawable/button_1_focused" android:state_focused= "true"/>< !--default state--><item android:drawable= "@drawable/button_1_normal"/></selector>

The properties of each state drawables ( button_1_selected , button_1_focused , button_1_normal ) must be defined in the corresponding Drawables directory:

Button_1_normal.xml

<shape xmlns:android= "Http://schemas.android.com/apk/res/android" >    <solid android:color= "@color/ Button_1_normal_background "/>    <corners android:radius=" 10dip "/></shape>

Button_1_focused.xml

<shape xmlns:android= "Http://schemas.android.com/apk/res/android" >    <solid android:color= "@color/ Button_1_focused_background "/>    <corners android:radius=" 10dip "/></shape>

Button_1_selected.xml

<shape xmlns:android= "Http://schemas.android.com/apk/res/android" >    <solid android:color= "@color/ Button_1_selected_background "/>    <corners android:radius=" 10dip "/></shape>

Then set the button background:

android:background= "@drawable/button_1_background"

This method is very flexible. However, when your app has many buttons and each button is different in color, it can be difficult to maintain all of the above XML files for each button. If you change the color of the button in the normal state, then you have to change the color of the other states. In the example above, each button requires 4 XML files. So what if your app has 10 or more buttons?

To clarify what I mean, please look at the following:

These come from a free product Bmex.

The two images are the app's home screen and the Send screen. Metro style is used in all two screens. Each screen has 6 buttons of different colors. and the color of the button will change depending on the state. A total of 12 buttons, so we need 12 drawable selector XML files and 24 drawable state XML files. And as the app grows, the software has to allow new screens and new buttons to be added. Maintaining these content is not a simple task.

To make the process simpler and more efficient, we have found a more effective solution-and have implemented it in a custom button view. This is an easy-to-initialize button. We call it Roundbutton because it supports rounded corners.

In another product, we need to highlight features, but we don't want to create custom views alone. So, let's add it to RoundButton the. Take a look at the following:

As you can see, we have the option of not selecting the buttons on the screen (the list chart at the top and the add icon after each element). When the button is selected, its highlighted state is set to true, and vice versa, false. And the button's appearance will be changed appropriately. In the example above, the highlight mode uses "image". In this mode, the visible pixels of the image are drawn as a highlight color.

First, we define the property set for Roundbutton. This is a set of properties that can be set through the layout XML.

Attrs_round_button.xml

<resources>    <declare-styleable name= "Roundbutton" >        <attr name= "image" format= "reference"/ >        <attr name= "bgcolor" format= "color"/> <attr name=        "text" format= "string"/>        <attr Name= "radius" format= "float"/>        <attr name= "HighlightColor" format= "color"/> <attr name=        " Highlightmode "format=" enum ">            <enum name=" None "value=" 0 "/>            <enum name=" image "value=" 1 "/>            <enum name= "Background" value= "2"/>        </attr>    </declare-styleable></resources >

We have added image , bgcolor ,text border fillet radius, HighlightColor and Highlightmode properties. The color of the pressed state is exported from bgcolor (described later).

Implement button

First, we need to implement constructors and parse parameters. We have created 3 different constructors:

Public Roundbutton (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, defstyle); Init (Attrs, Defstyle);} Public Roundbutton (context context, AttributeSet Attrs) {Super (context, attrs); Init (attrs, 0);} Public Roundbutton (Context context) {super (context); init (null, 0);}

All these constructors call the Init method.

Now we need to implement the Init method. It takes the property set and the default style as input parameters. In the Init method, we get the property value and initialize the internal variable. If the property set is NULL, then the default value is used.

 private void Init (attributeset attrs, int defstyle) {drawable image;int bgcolor; String text;if (Attrs! = null) {final TypedArray a = GetContext (). Obtainstyledattributes (Attrs,r.styleable.roundbutton, Defstyle, 0); image = A.getdrawable (r.styleable.roundbutton_image); bgcolor = A.getcolor (r.styleable.roundbutton_ bgcolor, 0xffffffff); text = a.getstring (r.styleable.roundbutton_text); radius = A.getfloat (r.styleable.roundbutton_ Radius, 12.0f); Highlightmode = Highlightmode.getvalue (A.getint (R.styleable.roundbutton_highlightmode, HighlightMode.None.ordinal ())); HighlightColor = A.getcolor (R.styleable.roundbutton_highlightcolor, 0xff00b5ff); A.recycle ();} else {image = Null;text = ""; bgcolor = 0xff808080;radius = 12.0f;highlightmode = Highlightmode.none;highlightcolor = 0xff0 0B5FF;} Init (image, bgcolor, text);}  

Then we create another Init method. This method is used to create the object and needs to render the contents of the button. The Init method here is declared public because it needs to be called when the Roundbutton is created. It creates the background and the pressed "paint"-objects that draw the background when the normal and pressed state are drawn. Press the color to select a brighter color than bgcolor. A way to lighten the color is explained later. The highlight mode is initialized here. If the background is set to highlight, create a highlight paint that is used to draw the background of the button when it is highlighted. If the image mode is set to highlight, create a highlighted image. The code for the image is created in the Createhighlightimage method, which is then given.

public void init (drawable image, int bgcolor, String text) {this.image = Image;bgpaint = new Paint (Paint.anti_alias_flag); Bgpaint.setcolor (bgcolor);p ressedbgpaint = new Paint (paint.anti_alias_flag);p Ressedbgpaint.setcolor (Brighter ( bgcolor)); if (text = = null) Text = ""; this.text = Text;textpaint = new Paint (paint.anti_alias_flag); Textpaint.setcolor ( 0xFFFFFFFF); textpaint.settextalign (Paint.Align.CENTER); Textpaint.settextsize (Pixelstosp (GetContext (), textSize) if (Highlightmode = = highlightmode.background) {highlightpaint = new Paint (Paint.anti_alias_flag); Highlightpaint.setcolor (HighlightColor);} else if (Highlightmode = = highlightmode.image) {highlightimage = Createhighlightimage ();} Setclickable (TRUE);}

To get the color value of the pressed state, we created the brighter method. It takes a color as an argument and returns a color that is brighter than that color. This method is also very simple:

 public void Init (drawable image, int bgcolor, String text) {this.image = image; Bgpaint = new Paint (Paint.anti_alias_flag), Bgpaint.setcolor (bgcolor);p ressedbgpaint = new Paint (paint.anti_alias_ FLAG);p Ressedbgpaint.setcolor (Brighter (bgcolor)); if (text = = null) Text = ""; this.text = Text;textpaint = new Paint (Paint . Anti_alias_flag); Textpaint.setcolor (0xFFFFFFFF); textpaint.settextalign (Paint.Align.CENTER); Textpaint.settextsize (Pixelstosp (GetContext (), textSize)); if (Highlightmode = = Highlightmode.background) { Highlightpaint = new Paint (paint.anti_alias_flag); Highlightpaint.setcolor (HighlightColor);} else if (Highlightmode = = highlightmode.image) {highlightimage = Createhighlightimage ();} Setclickable (True);}  

 private drawable createhighlightimage () {int width = image.getintrinsicwidth (); int height = image.getintrinsicheight (); Bitmap Bitmap = bitmap.createbitmap (width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new canvas (bitmap), image.setbounds (0, 0, width, height), Image.draw (canvas), int count = Bitmap.getwidth () * Bitmap.getheight (); int pixels[] = new Int[count];bitmap.getpixels (pixels, 0, bitmap.getwidth (), 0, 0, Bitmap.getwidth ( ), Bitmap.getheight ()), for (int n = 0; n < count; n++) {Boolean v = (Color.alpha (pixels[n]))! = 0;if (v) {int pixel = P Ixels[n];int alpha = Color.alpha (pixel); int red = color.red (highlightcolor); int green = Color.green (highlightcolor); int Blue = Color.Blue (highlightcolor); int Color = Color.argb (alpha, red, green, blue);p ixels[n] = Color;}} Bitmap.setpixels (pixels, 0, bitmap.getwidth (), 0, 0, bitmap.getwidth (), Bitmap.getheight ()); return new Bitmapdrawable ( Getresources (), bitmap);}  

In order to handle state changes, we need to handle touch events. So touch processing needs to be implemented. When we touch the button, its state changes to pressed (press), and the contents of the button are redrawn. When the button is not touched, its pressed flag is set to false and the contents of the button are redrawn.

@Overridepublic boolean ontouchevent (Motionevent event) {int action = event.getactionmasked (); switch (action) {case MotionEvent.ACTION_DOWN:pressed = True;invalidate (); Break;case MotionEvent.ACTION_UP:pressed = False;invalidate (); Break;case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_OUTSIDE:case MotionEvent.ACTION_HOVER_EXIT:pressed = False;invalidate (); break;} Return Super.ontouchevent (event);}

Then we implement the OnDraw button method. This method draws the contents of the button. This OnDraw method is called when the custom view is first displayed and every time it is redrawn.

protected void OnDraw (canvas canvas) {RECTF bounds = new RECTF (0, 0, getwidth (), GetHeight ());D rawable image = null; Paint bgpaint = Null;switch (highlightmode) {case none:image = This.image;bgpaint = pressed? pressedBgpaint:this.bgpain T;break;case background:image = this.image;if (pressed) Bgpaint = Pressedbgpaint;else Bgpaint = highlighted? Highlightpaint:this.bgpaint;break;case Image:image = highlighted? Highlightimage:this.image;bgpaint = pressed? Pressedbgpaint:this.bgpaint;break;} if (radius! = 0.0f) Canvas.drawroundrect (bounds, radius, radius, bgpaint); else canvas.drawrect (bounds, bgpaint); Rect textbounds = new rect (), if (Text.length () > 0) textpaint.gettextbounds (text, 0, Text.length (), textbounds), float h _DST = ((image = null)? Image.getminimumheight () + ((text.length () > 0)? spacing:0): 0) + textbounds.height (); Flo at xd = (bounds.width ()-((Image! = null)? Image.getminimumwidth (): 0)/2;float yd = (bounds.height ()-H_DST)/2; if (image = null) {ImagE.setbounds ((int) xd, (int) yd, (int) (XD + image.getminimumwidth ()), (int) (yd + image.getminimumheight ())), Image.draw (c Anvas);} Float XT = (bounds.width ()-0 * textbounds.width ())/2;float YT = yd + ((image = null)? Image.getminimumheight () + ((t Ext.length () > 0)? spacing:0): Textbounds.height ());//+ Textbounds.height (); Canvas.drawtext (text, XT, YT, Textpaint); if (checked &AMP;&A mp Checkable && Checkedimage! = null) {checkedimage.setbounds ((int) (Bounds.width ()- Checkedimage.getminimumwidth ()), (int) (Bounds.height ()-checkedimage.getminimumheight ()), (int) bounds.width (), ( int) bounds.height ()); Checkedimage.draw (canvas);}}
usage

In order to integrate Roundbutton into the code, you need to download the source code files. In the source code file, there are eclipse projects, source code, and XML resource files. You can copy them to your app project. or compile the Roundbutton project and add it as a library to your project.

If you are using a visual editor, select Roundbutton directly from the list of controls, and after adding it, set its properties.

In addition to the visual editor, Roundbutton can be inserted either from the layout XML or from the code. You can use this if you add it from the layout XML. Examples are as follows:

 <relativelayout xmlns:android= "http://schemas.android.com/apk/res/ Android "Android:layout_width=" Match_parent "android:layout_height=" Wrap_content "android:focusable=" false "an" Droid:focusableintouchmode= "false" android:descendantfocusability= "Blocksdescendants" android:orientation= " Horizontal "xmlns:app=" Http://schemas.android.com/apk/res/com.bitgriff.bamp "> < Com.bitgriff.bamp.helpers.RoundButton android:id= "@+id/button" app:radius= "0" app:image= "@drawable/ic_add Tomedialibrary "app:bgcolor=" @color/transparent "app:highlightmode=" image "Android:layout_width=" 40di P "android:layout_height=" 80dip "android:layout_centervertical=" true "android:layout_alignparentright = "true"/></RELATIVELAYOUT>  

Add Roundbutton from the code to create a new Roundbutton instance. Call its Init method to pass the image (nullable), Bgcolo, and text. and add Roundbutton to your viewgroup:

Roundbutton = new Roundbutton (context); Roundbutton.init (image, bgcolor, text);
further envisaged

In addition, we can also change RoundButton the shape. For example, make a circular button, as seen in many Android apps today. The image location (left, right, top, bottom) may also be configured. Wait a minute.

Summary

This article mainly describes how to implement a custom button that changes the background based on the state. This simple component can save us a lot of time. Hope to be useful to you.

links

Roundbutton Source Code

 

An efficient way to change the background color of Android buttons

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.