Tinting Your Android UI

Android is very flexible when it comes to creating a user interface (UI). By utilizing the Android Drawable class, it is possible to set a widget background to just about any image you want.

This is a great approach when you own the user experience, but what happens when you are not creating an app directly for the end user? For instance, suppose you are creating an app for retailers who want to customize the color scheme to their corporate colors. Or, you are creating a widget library for use by other developers. How do you allow someone to adjust the “theme” of your UI without packaging along an infinite number of graphic resources? The answer is in the Drawable class.

Each drawable has a color filter that can be applied in a number of interesting ways to achieve a wide array of variation in a UI at runtime. When used correctly, a color filter does not replace the original graphic resource but rather applies the change in hue uniformly; this preserves shadowing and gradient, while preventing the user from getting too crazy and inadvertently creating an eyesore.

In this example We will see ho we can apply a color filter to a standard Android button widget.

Setps:

1.) Create a new Android project in Eclipse.

2.) We will need two base drawables for our buttons: one in the normal state and one in the pressed state. When you are working with color filters, you will achieve the most dramatic result if your base image is a combination of grays. Write following into button_normal.xml:

 

<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:endColor="#808080"
android:centerColor="#ffffff"
android:startColor="#c0c0c0"
android:angle="270" />
<corners
android:radius="10dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>

 

 

3.) Write following into button_pressed.xml:

 

<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:endColor="#c0c0c0"
android:centerColor="#c0c0c0"
android:startColor="#c0c0c0"
android:angle="270" />
<stroke android:width="10px"
android:color="#808080"/>
<corners
android:radius="10dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>

 

 

4.) Create and write following into button_states.xml:

 

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="@drawable/button_pressed" />
<item
android:state_pressed="false"
android:drawable="@drawable/button_normal" />
</selector>

 

 

5.) In our /res/layout folder, we are ready to define our widget layout. In this case, we have a linear layout that stacks five buttons vertically. Each button has its background property set to our recently created state list. Write following into activity_main.xml:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_margin="8dp"
android:orientation="vertical"
android:background="#000000" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:text="Dynamic Tint Effect Demo"
android:layout_margin="8dp"
android:textSize="20sp" />

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:id="@+id/button_1"
android:background="@drawable/button_states"
android:text="text"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:id="@+id/button_2"
android:background="@drawable/button_states"
android:text="text"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:id="@+id/button_3"
android:background="@drawable/button_states"
android:text="text"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:id="@+id/button_4"
android:background="@drawable/button_states"
android:text="text"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:id="@+id/button_5"
android:background="@drawable/button_states"
android:text="text"/>
</LinearLayout>

 

 

6.) We are ready to code the /src/MainActivity.java class. We will start by extending the base Activity, implementing an OnClickListener, and creating our own utility that allows us to get resources by their text name rather than the more commonly used ID. Write following into MainActivity.java:

 

package com.authorwjf.tinted;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;

public class MainActivity extends Activity implements OnClickListener {

private String[] colors = {"white", "magenta", "yellow", "cyan", "green"};
private int index = 0;

private int getIdFromName(String name) {
return getResources().getIdentifier(name,"id",getPackageName());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i=0; i<5; i++) {
String name = "button_"+Integer.toString(i+1);
findViewById(getIdFromName(name)).setOnClickListener(this);
}
onClick(null);
}
@Override
public void onClick(View v) {
for (int i=0; i<5; i++) {
String name = "button_"+Integer.toString(i+1);
((Button)findViewById(getIdFromName(name))).setText(colors[index]);
int tint = Color.parseColor(colors[index]);
((Button)findViewById(getIdFromName(name))).getBackground().setColorFilter(tint, Mode.MULTIPLY);
}
index++;
if (index>4) index=0;
}
}

 

 

OutPut

drawable1

drawable2

Leave a Comment: