Sunday, January 25, 2009

Android Widget - through Java Code

There are two ways to create android resources/view - either through the XML layout or through pure java code. In this article I have tried to implement the android view through the second method - i.e. through Java code. I have implemented a Table Layout and few widgets like static text, edit box and slider bar. There are three sets of all these widgets - namely Red, Green and Blue. These three are the percentage of the RGB color code. For example if we make Red as 100, and Green and Blue as 0, it will paint the background of the device with Red. It has also shown how to create a prompt dialog when you enter a value more than 100 in any of the edit boxes.

The application will look like the following:



The code for this application is as follow -

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.SeekBar.OnSeekBarChangeListener;

public class Widget extends Activity implements View.OnClickListener /*, View.OnKeyListener */{
/** Called when the activity is first created. */

private final static int idLayout = 1;
private final static int idTitle = 2;

private final static int idTextRed = 3;
private final static int idTextGreen = 4;
private final static int idTextBlue = 5;

private final static int idEditRedText = 6;
private final static int idEditGreenText = 7;
private final static int idEditBlueText = 8;

private final static int idSeekBarRed = 9;
private final static int idSeekBarGreen = 10;
private final static int idSeekBarBlue =11;

private final static int idButtonOK = 12;

private final static int MaxColorValue = 255;

private int RedProgress = 0;
private int GreenProgress = 0;
private int BlueProgress = 0;

private int RedValue = 0;
private int GreenValue = 0;
private int BlueValue = 0;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);


setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

TableLayout layout = new TableLayout(this);
layout.setId(idLayout);
layout.setLayoutParams(
new LayoutParams(LayoutParams.FILL_PARENT,android.view.ViewGroup.LayoutParams.FILL_PARENT));
layout.setFocusable(true);

TextView title = new TextView(this);
title.setText(R.string.title);
title.setLayoutParams(
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
//title.s(Alignment.ALIGN_CENTER);
title.setId(idTitle);
layout.addView(title,0);


//For Item 1
TextView ItemRed = new TextView(this);
ItemRed.setFocusable(true);
ItemRed.setText("% RED");
ItemRed.setTextColor(Color.LTGRAY);
ItemRed.setLayoutParams(
new TableLayout.LayoutParams(
TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));

//Give the menu item an ID for tracking reasons.
//The ID is a static int defined locally to the class
ItemRed.setId(idTextRed);
//Add it to our linear layout
layout.addView(ItemRed, 1);

EditText EditTextRed = new EditText(this);
EditTextRed.setFocusable(true);
EditTextRed.setLayoutParams(
new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
EditTextRed.setId(idEditRedText);

layout.addView(EditTextRed, 2);

SeekBar SeekBarRed = new SeekBar(this);
SeekBarRed.setFocusable(true);
SeekBarRed.setLayoutParams(
new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
SeekBarRed.setMax(MaxColorValue);
SeekBarRed.setId(idSeekBarRed);


layout.addView(SeekBarRed, 3);


//For item 2
TextView ItemGreen = new TextView(this);
ItemGreen.setFocusable(true);
ItemGreen.setText("% GREEN");
ItemGreen.setTextColor(Color.LTGRAY);
ItemGreen.setLayoutParams(
new TableLayout.LayoutParams(
TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));


//Give the menu item an ID for tracking reasons.
//The ID is a static int defined locally to the class
ItemGreen.setId(idTextGreen);
//Add it to our linear layout
layout.addView(ItemGreen, 4);

EditText EditTextGreen = new EditText(this);
EditTextGreen.setFocusable(true);
EditTextGreen.setLayoutParams(
new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
EditTextRed.setId(idEditGreenText);

layout.addView(EditTextGreen, 5);

SeekBar SeekBarGreen = new SeekBar(this);
SeekBarGreen.setFocusable(true);
SeekBarGreen.setLayoutParams(
new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
SeekBarGreen.setMax(MaxColorValue);
SeekBarGreen.setId(idSeekBarGreen);
layout.addView(SeekBarGreen, 6);


TextView ItemBlue = new TextView(this);
ItemBlue.setFocusable(true);
ItemBlue.setText("% BLUE");
ItemBlue.setTextColor(Color.LTGRAY);
ItemBlue.setLayoutParams(
new TableLayout.LayoutParams(
TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));


//Give the menu item an ID for tracking reasons.
//The ID is a static int defined locally to the class
ItemBlue.setId(idTextBlue);
//Add it to our linear layout
layout.addView(ItemBlue, 7);


EditText EditTextBlue = new EditText(this);
EditTextBlue.setFocusable(true);
EditTextBlue.setLayoutParams(
new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
EditTextBlue.setId(idEditBlueText);

layout.addView(EditTextBlue, 8);

SeekBar SeekBarBlue = new SeekBar(this);
SeekBarBlue.setFocusable(true);
SeekBarBlue.setLayoutParams(
new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
SeekBarBlue.setMax(MaxColorValue);
SeekBarBlue.setId(idSeekBarBlue);
layout.addView(SeekBarBlue, 9);

Button OKBtn = new Button(this);
OKBtn.setFocusable(true);
OKBtn.setLayoutParams(
new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
OKBtn.setId(idButtonOK);
OKBtn.setText("OK");
layout.addView(OKBtn,10);


setContentView(layout);

OKBtn.setOnClickListener(this);

SeekBarRed.setOnSeekBarChangeListener(OnSeekBarProgress);
SeekBarGreen.setOnSeekBarChangeListener(OnSeekBarProgress);
SeekBarBlue.setOnSeekBarChangeListener(OnSeekBarProgress);
}

OnSeekBarChangeListener OnSeekBarProgress =
new OnSeekBarChangeListener() {

public void onProgressChanged(SeekBar s, int progress, boolean touch){

if(touch){
TableLayout layout = (TableLayout)s.getParent();

EditText Red = (EditText)layout.getChildAt(2);
EditText Green = (EditText)layout.getChildAt(5);
EditText Blue = (EditText)layout.getChildAt(8);

if(s.getId()== idSeekBarRed ){
RedProgress = progress;
Red.setText(Integer.toString(RedProgress*100/254));
}

if(s.getId()== idSeekBarGreen ){

GreenProgress = progress;
Green.setText(Integer.toString(GreenProgress*100/254));
}


if(s.getId()== idSeekBarBlue ){

BlueProgress = progress;
Blue.setText(Integer.toString(BlueProgress*100/254));
}

int color = Color.rgb(RedProgress, GreenProgress, BlueProgress);
layout.setBackgroundColor(color);

}
}

public void onStartTrackingTouch(SeekBar s){

}

public void onStopTrackingTouch(SeekBar s){

}
};


public void onClick(View v){

Button b = (Button)v;

if(b.getId() == idButtonOK){

TableLayout layout = (TableLayout)(v.getParent());

EditText Red = (EditText)layout.getChildAt(2);
EditText Green = (EditText)layout.getChildAt(5);
EditText Blue = (EditText)layout.getChildAt(8);

SeekBar SeekBarRed = (SeekBar)layout.getChildAt(3);
SeekBar SeekBarGreen = (SeekBar)layout.getChildAt(6);
SeekBar SeekBarBlue = (SeekBar)layout.getChildAt(9);


String RedText = Red.getText().toString();
String GreenText = Green.getText().toString();
String BlueText = Blue.getText().toString();


if(!("".equals(RedText))) {
try {
RedValue = Integer.parseInt(RedText);
}
catch (NumberFormatException e) {
}
}
else
RedValue = 0;


if(!("".equals(GreenText))) {
try {
GreenValue = Integer.parseInt(GreenText);
}
catch (NumberFormatException e) {
}
}
else
GreenValue = 0;

if(!("".equals(BlueText))) {
try {
BlueValue = Integer.parseInt(BlueText);
}
catch (NumberFormatException e) {
}
}
else
BlueValue = 0;


if( RedValue>=0 && RedValue<=100) {
RedProgress = 254*RedValue/100;
SeekBarRed.setProgress(RedProgress);
}

else {
new AlertDialog.Builder(this)
.setTitle("Alert!")
.setMessage("Please enter a value between 0 and 100 for RED...")
.setNeutralButton("Close", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
// do nothing – it will close on its own
}
})
.show();
}

if( GreenValue>=0 && GreenValue<=100) {
GreenProgress = 254*GreenValue/100;
SeekBarGreen.setProgress(GreenProgress);
}

else {
new AlertDialog.Builder(this)
.setTitle("Alert!")
.setMessage("Please enter a value between 0 and 100 for GREEN...")
.setNeutralButton("Close", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
// do nothing – it will close on its own
}
})
.show();
}

if(BlueValue>=0 && BlueValue<=100) {
BlueProgress = 254*BlueValue/100;
SeekBarBlue.setProgress(BlueProgress);
}

else {
new AlertDialog.Builder(this)
.setTitle("Alert!")
.setMessage("Please enter a value between 0 and 100 for BLUE...")
.setNeutralButton("Close", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
// do nothing – it will close on its own
}
})
.show();
}

int color = Color.rgb(RedProgress, GreenProgress, BlueProgress);
layout.setBackgroundColor(color);

}

};
}


Play around with it.

Feel happy to work in Android...

5 comments:

Unknown said...

Som, nice work! I had to XML-ize the layout section (convert paragraph marks to angle brackets), but it works beautifully and demonstrates a lot of the power you can get when you customize your own buttons and dials. Thanks!

Frank said...

Hi,
I have a question,is it possible to add layout/layouts dynamically through code to a R.layout.main xml file which is static and display the Updated main.xml file by calling setContentView(R.layout.main)

is it possible to do that way?

if yes-- can you pls show me a code snippet?

Thnak you.

Frank said...

Hi,
good post.It was useful 4 me to start building UI through code.And

I have a question,
is it possible to add Layout/Layouts dynamically through code to a static xml layout file ,eg R.Layout.Main, and display the updated Main.xml by calling setContentView(R.Layout.main)

if yes,can you pls show me a code snippent??

thank you.

Unknown said...

hello :)
this was alot helpful as i wanted to build my layout through code.
is there a way to change buttons or textview positions dynamically at run time? which layout would be better used? and how can i do it?
if you know, ur help is alot appreciatd :)
thank you

Somenath said...

Frank, to do that give an id to your layout. get a reference to that layout using finfViewById. then you can dynamically add whatever you want to that layout...