page.title=Form Stuff parent.title=Hello, Views parent.link=index.html @jd:body
This tutorial introduces a variety of widgets that are useful when creating forms, such as image buttons, text fields, checkboxes and radio buttons.
res/layout/main.xml
file should already have a basic {@link
android.widget.LinearLayout}:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > </LinearLayout>
For each widget you want to add, just put the respective View inside this {@link android.widget.LinearLayout}.
Each section below also assumes that your HelloFormStuff
Activity has the following
default implementation of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }
Now select which kind of form widget you'd like to create:
In this section, you will create a button with a custom image instead of text, using the {@link android.widget.Button} widget and an XML file that defines three different images to use for the different button states. When the button is pressed, a short message will be displayed.
res/drawable/
directory of
your project. These will be used for the different button states.res/drawable/
directory named
android_button.xml
.
Insert the following XML:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/android_pressed" android:state_pressed="true" /> <item android:drawable="@drawable/android_focused" android:state_focused="true" /> <item android:drawable="@drawable/android_normal" /> </selector>
This defines a single drawable resource, which will change its image based on the current
state of the button. The first <item>
defines
android_pressed.png
as the image when the button is pressed (it's been
activated); the second <item>
defines android_focused.png
as the image
when the button is focused (when the button is highlighted using the trackball or directional
pad); and the third <item>
defines android_normal.png
as the image
for the normal state (when neither pressed nor focused). This XML file now represents a single
drawable resource and when referenced by a {@link android.widget.Button} for its background,
the image displayed will change based on these three states.
Note: The order of the <item>
elements is
important. When this drawable is referenced, the <item>
s are traversed in-order to
determine which one is appropriate for the current button state. Because the "normal" image is last,
it is only applied when the conditions android:state_pressed
and
android:state_focused
have both evaluated false.
res/layout/main.xml
file and add the {@link
android.widget.Button} element:
<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" android:background="@drawable/android_button" android:onClick="onButtonClicked"/>
The android:background
attribute specifies the drawable resource to use for the
button background (which, when saved at res/drawable/android.xml
, is
referenced as @drawable/android
). This replaces the normal background image
applied by the system with the drawable created above, which changes its image based on
the button state.
The attribute android:onClick
specifies the name of a method in your activity
that the system should call when the user clicks the button. You'll create that method next.
public void onButtonClicked(View v) { // Do something when the button is clicked Toast.makeText(HelloFormStuff.this, "Button clicked", Toast.LENGTH_SHORT).show(); }
When you specify this kind of method, which is used in your layout file with the {@code
android:onClick} attribute, the method must be public
, have a void
return
value, and accept a single {@code android.view.View} parameter. When the system calls this method,
it passes the {@code android.view.View} that was clicked.
In this section, you will create a text field for user input, using the {@link android.widget.EditText} widget. Once text has been entered into the field, the "Enter" key will display the text in a toast message.
res/layout/main.xml
file and add the {@link android.widget.EditText}
element (inside the {@link android.widget.LinearLayout}):
<EditText android:id="@+id/edittext" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
final EditText edittext = (EditText) findViewById(R.id.edittext); edittext.setOnKeyListener(new OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { // If the event is a key-down event on the "enter" button if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { // Perform action on key press Toast.makeText(HelloFormStuff.this, edittext.getText(), Toast.LENGTH_SHORT).show(); return true; } return false; } });
This captures the {@link android.widget.EditText} element from the layout and adds an {@link
android.view.View.OnKeyListener}. The {@link android.view.View.OnKeyListener} must implement the
{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent)} method, which
defines the action to be made when a key is pressed while the widget has focus. In this case, the
method is defined to listen for the Enter key (when pressed down), then pop up a {@link
android.widget.Toast} message with the text that has been entered. The {@link
android.view.View.OnKeyListener#onKey(View,int,KeyEvent)} method should always return
true
if the event has been handled, so that the event doesn't bubble-up (which would
result in a carriage return in the text field).
In this section, you will create a checkbox for selecting items, using the {@link android.widget.CheckBox} widget. When the checkbox is pressed, a toast message will indicate the current state of the checkbox.
res/layout/main.xml
file and add the {@link android.widget.CheckBox}
element (inside the {@link android.widget.LinearLayout}):
<CheckBox android:id="@+id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="check it out" android:onClick="onCheckboxClicked"/>
The attribute android:onClick
specifies the name of a method in your activity
that the system should call when the user clicks the check box. You'll create that method next.
public void onCheckboxClicked(View v) { // Perform action on clicks, depending on whether it's now checked if (((CheckBox) v).isChecked()) { Toast.makeText(HelloFormStuff.this, "Selected", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(HelloFormStuff.this, "Not selected", Toast.LENGTH_SHORT).show(); } }
When you specify this kind of method, which is used in your layout file with the {@code
android:onClick}
attribute, the method must be public
, have a void
return value, and
accept a single {@code android.view.View} parameter. When the system calls this method, it
passes the {@code android.view.View} that was clicked. In this example, the {@code
android.view.View} is cast to a {@link android.widget.CheckBox} to determine whether the widget
has been checked or unchecked. The {@link android.widget.CheckBox} widget
handles its own state changes, so you only need to query the current state.
Tip: If you need to change the state yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link android.widget.CompoundButton#toggle()} method.
In this section, you will create two mutually-exclusive radio buttons (enabling one disables the other), using the {@link android.widget.RadioGroup} and {@link android.widget.RadioButton} widgets. When either radio button is pressed, a toast message will be displayed.
res/layout/main.xml
file and add two {@link
android.widget.RadioButton}s, nested in a {@link android.widget.RadioGroup} (inside the {@link
android.widget.LinearLayout}):
<RadioGroup android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <RadioButton android:id="@+id/radio_red" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Red" android:onClick="onRadioButtonClicked"/> <RadioButton android:id="@+id/radio_blue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Blue" android:onClick="onRadioButtonClicked"/> </RadioGroup>
It's important that the {@link android.widget.RadioButton}s are grouped together by the {@link android.widget.RadioGroup} element so that no more than one can be selected at a time. This logic is automatically handled by the Android system. When one {@link android.widget.RadioButton} within a group is selected, all others are automatically deselected.
The attribute android:onClick
specifies the name of a method in your activity
that the system should call when the user clicks the radio button. You'll create that method
next.
public void onRadioButtonClicked(View v) { // Perform action on clicks RadioButton rb = (RadioButton) v; Toast.makeText(HelloFormStuff.this, rb.getText(), Toast.LENGTH_SHORT).show(); }
When you specify this kind of method, which is used in your layout file with the {@code
android:onClick}
attribute, the method must be public
, have a void
return value, and
accept a single {@code android.view.View} parameter. When the system calls this method, it
passes the {@code android.view.View} that was clicked.
Because each {@link android.widget.RadioButton} widget is grouped into a {@link android.widget.RadioGroup}, each widget handles its own state changes when a new button is selected.
Tip: If you need to change the state yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link android.widget.CompoundButton#toggle()} method.
In this section, you'll create a button used specifically for toggling between two states, using the {@link android.widget.ToggleButton} widget. This widget is an excellent alternative to radio buttons if you have two simple states that are mutually exclusive ("on" and "off", for example).
res/layout/main.xml
file and add the {@link android.widget.ToggleButton}
element (inside the {@link android.widget.LinearLayout}):
<ToggleButton android:id="@+id/togglebutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="Vibrate on" android:textOff="Vibrate off" android:onClick="onToggleClicked"/>
The attributes android:textOn
and android:textOff
specify the text
for the button when the button has been toggled on or off. The default values are "ON" and
"OFF".
The attribute android:onClick
specifies the name of a method in your activity
that the system should call when the user clicks the button. You'll create that method next.
public void onToggleClicked(View v) { // Perform action on clicks if (((ToggleButton) v).isChecked()) { Toast.makeText(HelloFormStuff.this, "Toggle on", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(HelloFormStuff.this, "Toggle off", Toast.LENGTH_SHORT).show(); } }
When you specify this kind of method, which is used in your layout file with the {@code
android:onClick}
attribute, the method must be public
, have a void
return value, and
accept a single {@code android.view.View} parameter. When the system calls this method, it
passes the {@code android.view.View} that was clicked.
In this example, the callback method checks the new state of the button, then shows a {@link android.widget.Toast} message that indicates the current state.
Notice that the {@link android.widget.ToggleButton} handles its own state change between checked and unchecked, so you just ask which it is.
Tip: If you need to change the state yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link android.widget.CompoundButton#toggle()} method.
In this section, you'll create a widget that allows the user to provide a rating, with the {@link android.widget.RatingBar} widget.
res/layout/main.xml
file and add the {@link android.widget.RatingBar}
element (inside the {@link android.widget.LinearLayout}):
<RatingBar android:id="@+id/ratingbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:numStars="5" android:stepSize="1.0"/>
The android:numStars
attribute defines how many stars to display for the rating
bar. The android:stepSize
attribute defines the granularity for each
star (for example, a value of 0.5
would allow half-star ratings).
final RatingBar ratingbar = (RatingBar) findViewById(R.id.ratingbar); ratingbar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() { public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { Toast.makeText(HelloFormStuff.this, "New Rating: " + rating, Toast.LENGTH_SHORT).show(); } });
This captures the {@link android.widget.RatingBar} widget from the layout with {@link android.app.Activity#findViewById(int)} and then sets an {@link android.widget.RatingBar.OnRatingBarChangeListener}. The {@link android.widget.RatingBar.OnRatingBarChangeListener#onRatingChanged(RatingBar,float,boolean) onRatingChanged()} callback method then defines the action to perform when the user sets a rating. In this case, a simple {@link android.widget.Toast} message displays the new rating.
If you've added all the form widgets above, your application should look like this: