Home | History | Annotate | Download | only in views
      1 page.title=Form Stuff
      2 parent.title=Hello, Views
      3 parent.link=index.html
      4 @jd:body
      5 
      6 <p>This tutorial introduces a variety of widgets that are useful when creating forms, such as
      7 image buttons, text fields, checkboxes and radio buttons.</p>
      8 
      9 
     10 <ol>
     11   <li>Start a new project named <em>HelloFormStuff</em>.</li>
     12   <li>Your <code>res/layout/main.xml</code> file should already have a basic {@link
     13 android.widget.LinearLayout}:
     14 <pre>
     15 &lt;?xml version="1.0" encoding="utf-8"?>
     16 &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     17     android:orientation="vertical"
     18     android:layout_width="fill_parent"
     19     android:layout_height="fill_parent" >
     20 &lt;/LinearLayout>
     21 </pre>
     22     <p>For each widget you want to add, just put the respective View inside this {@link
     23 android.widget.LinearLayout}.</p>
     24   </li>
     25 </ol>
     26 <p>Each section below also assumes that your <code>HelloFormStuff</code> Activity has the following
     27 default implementation of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:</p>
     28 <pre>
     29 public void onCreate(Bundle savedInstanceState) {
     30     super.onCreate(savedInstanceState);
     31     setContentView(R.layout.main);
     32 }
     33 </pre>
     34 
     35 <p>Now select which kind of form widget you'd like to create:</p>
     36 <ul>
     37   <li><a href="#CustomButton">Custom Button</a></li>
     38   <li><a href="#EditText">Edit Text</a></li>
     39   <li><a href="#Checkbox">Checkbox</a></li>
     40   <li><a href="#RadioButtons">Radio Buttons</a></li>
     41   <li><a href="#ToggleButton">Toggle Button</a></li>
     42   <li><a href="#RatingBar">Rating Bar</a></li>
     43 </ul>
     44 
     45 
     46 
     47 <h2 id="CustomButton">Custom Button</h2>
     48 
     49 <p>In this section, you will create a button with a custom image instead of text, using the {@link
     50 android.widget.Button} widget and an XML file that defines three different images to use for the
     51 different button states. When the button is pressed, a short message will be displayed.</p>
     52 
     53 <img src="images/android_pressed.png" style="float:right;" title="android_pressed.png"/>
     54 <img src="images/android_focused.png" style="float:right;clear:right;" title="android_focused.png"/>
     55 <img src="images/android_normal.png" style="float:right;clear:right;" title="android_normal.png"/>
     56 <ol>
     57   <li>Copy the images on the right into the <code>res/drawable/</code> directory of
     58 your project. These will be used for the different button states.</li>
     59   <li>Create a new file in the <code>res/drawable/</code> directory named
     60 <code>android_button.xml</code>.
     61 Insert the following XML:
     62 <pre>
     63 &lt;?xml version="1.0" encoding="utf-8"?>
     64 &lt;selector xmlns:android="http://schemas.android.com/apk/res/android">
     65     &lt;item android:drawable="@drawable/android_pressed"
     66           android:state_pressed="true" />
     67     &lt;item android:drawable="@drawable/android_focused"
     68           android:state_focused="true" />
     69     &lt;item android:drawable="@drawable/android_normal" />
     70 &lt;/selector>
     71 </pre>
     72   <p>This defines a single drawable resource, which will change its image based on the current
     73 state of the button. The first <code>&lt;item></code> defines
     74 <code>android_pressed.png</code> as the image when the button is pressed (it's been
     75 activated); the second <code>&lt;item></code> defines <code>android_focused.png</code> as the image
     76 when the button is focused (when the button is highlighted using the trackball or directional
     77 pad); and the third <code>&lt;item></code> defines <code>android_normal.png</code> as the image
     78 for the normal state (when neither pressed nor focused). This XML file now represents a single
     79 drawable resource and when referenced by a {@link android.widget.Button} for its background,
     80 the image displayed will change based on these three states.</p>
     81   <p class="note"><strong>Note:</strong> The order of the <code>&lt;item></code> elements is
     82 important. When this drawable is referenced, the  <code>&lt;item></code>s are traversed in-order to
     83 determine which one is appropriate for the current button state. Because the "normal" image is last,
     84 it is only applied when the conditions <code>android:state_pressed</code> and
     85 <code>android:state_focused</code> have both evaluated false.</li>
     86   <li>Open the <code>res/layout/main.xml</code> file and add the {@link
     87 android.widget.Button} element:
     88 <pre>
     89     &lt;Button
     90         android:id="@+id/button"
     91         android:layout_width="wrap_content"
     92         android:layout_height="wrap_content"
     93         android:padding="10dp"
     94         android:background="@drawable/android_button" />
     95 </pre>
     96 	<p>The <code>android:background</code> attribute specifies the drawable resource to use for the
     97 button background (which, when saved at <code>res/drawable/android.xml</code>, is
     98 referenced as <code>@drawable/android</code>). This replaces the normal background image
     99 used for buttons throughout the system. In order for the drawable to change its image based on
    100 the button state, the image must be applied to the background.</p>
    101 </li>
    102 
    103 <li>To make the button do something when pressed, add the following
    104 code at the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
    105 <pre>
    106 final Button button = (Button) findViewById(R.id.button);
    107 button.setOnClickListener(new OnClickListener() {
    108     public void onClick(View v) {
    109         // Perform action on clicks
    110         Toast.makeText(HelloFormStuff.this, "Beep Bop", Toast.LENGTH_SHORT).show();
    111     }
    112 });
    113 </pre>
    114 <p>This captures the {@link android.widget.Button} from the layout, then adds an {@link
    115 android.view.View.OnClickListener}. The {@link android.view.View.OnClickListener}
    116 must implement the {@link android.view.View.OnClickListener#onClick(View)} callback method, which
    117 defines the action to be made when the button is clicked. In this example, a
    118 {@link android.widget.Toast} message will be displayed.</p>
    119 </li>
    120 <li>Now run the application.</li>
    121 </ol>
    122 
    123 
    124 
    125 <h2 id="EditText">Edit Text</h2>
    126 
    127 <p>In this section, you will create a text field for user input, using the {@link
    128 android.widget.EditText} widget. Once text has been entered into the field, the "Enter" key will
    129 display the text in a toast message.</p>
    130 
    131 <ol>
    132   <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.EditText}
    133 element (inside the {@link android.widget.LinearLayout}):
    134 <pre>
    135     &lt;EditText
    136         android:id="@+id/edittext"
    137         android:layout_width="fill_parent"
    138         android:layout_height="wrap_content"/>
    139 </pre>
    140 </li>
    141 <li>To do something with the text that the user types, add the following code
    142 to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
    143 <pre>
    144 final EditText edittext = (EditText) findViewById(R.id.edittext);
    145 edittext.setOnKeyListener(new OnKeyListener() {
    146     public boolean onKey(View v, int keyCode, KeyEvent event) {
    147         // If the event is a key-down event on the "enter" button
    148         if ((event.getAction() == KeyEvent.ACTION_DOWN) &amp;&amp;
    149             (keyCode == KeyEvent.KEYCODE_ENTER)) {
    150           // Perform action on key press
    151           Toast.makeText(HelloFormStuff.this, edittext.getText(), Toast.LENGTH_SHORT).show();
    152           return true;
    153         }
    154         return false;
    155     }
    156 });
    157 </pre>
    158 <p>This captures the {@link android.widget.EditText} element from the layout and adds an {@link
    159 android.view.View.OnKeyListener}. The {@link android.view.View.OnKeyListener} must implement the
    160 {@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent)} method, which
    161 defines the action to be made when a key is pressed while the widget has focus. In this case, the
    162 method is defined to listen for the Enter key (when pressed down), then pop up a {@link
    163 android.widget.Toast} message with the text that has been entered. The {@link
    164 android.view.View.OnKeyListener#onKey(View,int,KeyEvent)} method should always return
    165 <code>true</code> if the event has been handled, so that the event doesn't bubble-up (which would
    166 result in a carriage return in the text field).</p>
    167 </li>
    168 <li>Run the application.</li>
    169 </ol>
    170 
    171 
    172 
    173 <h2 id="Checkbox">Checkbox</h2>
    174 
    175 <p>In this section, you will create a checkbox for selecting items, using the {@link
    176 android.widget.CheckBox} widget. When the checkbox is pressed, a toast message will
    177 indicate the current state of the checkbox.</p>
    178 
    179 <ol>
    180   <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.CheckBox}
    181 element (inside the {@link android.widget.LinearLayout}):
    182 <pre>
    183     &lt;CheckBox android:id="@+id/checkbox"
    184         android:layout_width="wrap_content"
    185         android:layout_height="wrap_content"
    186         android:text="check it out" />
    187 </pre>
    188 </li>
    189 <li>To do something when the state is changed, add the following code
    190 to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
    191 <pre>
    192 final CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox);
    193 checkbox.setOnClickListener(new OnClickListener() {
    194     public void onClick(View v) {
    195         // Perform action on clicks, depending on whether it's now checked
    196         if (((CheckBox) v).isChecked()) {
    197             Toast.makeText(HelloFormStuff.this, "Selected", Toast.LENGTH_SHORT).show();
    198         } else {
    199             Toast.makeText(HelloFormStuff.this, "Not selected", Toast.LENGTH_SHORT).show();
    200         }
    201     }
    202 });
    203 </pre>
    204 <p>This captures the {@link android.widget.CheckBox} element from the layout, then adds an {@link
    205 android.view.View.OnClickListener}. The {@link android.view.View.OnClickListener} must implement the
    206 {@link android.view.View.OnClickListener#onClick(View)} callback method, which
    207 defines the action to be made when the checkbox is clicked. When clicked, {@link
    208 android.widget.CompoundButton#isChecked()} is called to check the new state of the check box. If it
    209 has been checked, then a {@link android.widget.Toast} displays the message "Selected", otherwise it
    210 displays "Not selected". Note that the {@link android.view.View} object that is passed in the {@link
    211 android.view.View.OnClickListener#onClick(View)} callback must be cast to a {@link
    212 android.widget.CheckBox} because the {@link android.widget.CompoundButton#isChecked()} method is
    213 not defined by the parent {@link android.view.View} class. The {@link android.widget.CheckBox}
    214 handles its own state changes, so you only need to query the current state.</p>
    215 </li>
    216 <li>Run it.</li>
    217 </ol>
    218 <p class="note"><strong>Tip:</strong> If you need to change the state
    219 yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}),
    220 use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link
    221 android.widget.CompoundButton#toggle()} method.</p>
    222 
    223 
    224 
    225 <h2 id="RadioButtons">Radio Buttons</h2>
    226 
    227 <p>In this section, you will create two mutually-exclusive radio buttons (enabling one disables
    228 the other), using the {@link android.widget.RadioGroup} and {@link android.widget.RadioButton}
    229 widgets. When either radio button is pressed, a toast message will be displayed.</p>
    230 
    231 <ol>
    232   <li>Open the <code>res/layout/main.xml</code> file and add two {@link
    233 android.widget.RadioButton}s, nested in a {@link android.widget.RadioGroup} (inside the {@link
    234 android.widget.LinearLayout}):
    235 <pre>
    236     &lt;RadioGroup
    237       android:layout_width="fill_parent"
    238       android:layout_height="wrap_content"
    239       android:orientation="vertical">
    240       &lt;RadioButton android:id="@+id/radio_red"
    241           android:layout_width="wrap_content"
    242           android:layout_height="wrap_content"
    243           android:text="Red" />
    244       &lt;RadioButton android:id="@+id/radio_blue"
    245           android:layout_width="wrap_content"
    246           android:layout_height="wrap_content"
    247           android:text="Blue" />
    248     &lt;/RadioGroup>
    249 </pre>
    250 <p>It's important that the {@link android.widget.RadioButton}s are grouped together by the {@link
    251 android.widget.RadioGroup} element so that no more than one can be selected at a time. This logic
    252 is automatically handled by the Android system. When one {@link android.widget.RadioButton} within
    253 a group is selected, all others are automatically deselected.</p>
    254 </li>
    255 
    256 <li>To do something when each {@link android.widget.RadioButton} is selected, you need an
    257 {@link android.view.View.OnClickListener}. In this case, you want the listener to be re-usable, so
    258 add the following code to create a new member in the <code>HelloFormStuff</code> Activity:
    259 <pre>
    260 private OnClickListener radio_listener = new OnClickListener() {
    261     public void onClick(View v) {
    262         // Perform action on clicks
    263         RadioButton rb = (RadioButton) v;
    264         Toast.makeText(HelloFormStuff.this, rb.getText(), Toast.LENGTH_SHORT).show();
    265     }
    266 };
    267 </pre>
    268 <p>First, the {@link android.view.View} that is passed to the {@link
    269 android.view.View.OnClickListener#onClick(View)} method is cast into a RadioButton. Then a
    270 {@link android.widget.Toast} message displays the selected radio button's text.</p>
    271 <li>Now, at the bottom of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method, add
    272 the following:
    273 <pre>
    274   final RadioButton radio_red = (RadioButton) findViewById(R.id.radio_red);
    275   final RadioButton radio_blue = (RadioButton) findViewById(R.id.radio_blue);
    276   radio_red.setOnClickListener(radio_listener);
    277   radio_blue.setOnClickListener(radio_listener);
    278 </pre>
    279 <p>This captures each of the {@link android.widget.RadioButton}s from the layout and adds the
    280 newly-created {@link android.view.View.OnClickListener} to each.</p>
    281 <li>Run the application.</li>
    282 </ol>
    283 
    284 <p class="note"><strong>Tip:</strong> If you need to change the state
    285 yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}),
    286 use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link
    287 android.widget.CompoundButton#toggle()} method.</p>
    288 
    289 
    290 
    291 <h2 id="ToggleButton">Toggle Button</h2>
    292 
    293 <p>In this section, you'll create a button used specifically for toggling between two
    294 states, using the {@link android.widget.ToggleButton} widget. This widget is an excellent
    295 alternative to radio buttons if you have two simple states that are mutually exclusive ("on" and
    296 "off", for example).</p>
    297 
    298 <ol>
    299   <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.ToggleButton}
    300 element (inside the {@link android.widget.LinearLayout}):
    301 <pre>
    302     &lt;ToggleButton android:id="@+id/togglebutton"
    303         android:layout_width="wrap_content"
    304         android:layout_height="wrap_content"
    305         android:textOn="Vibrate on"
    306         android:textOff="Vibrate off"/>
    307 </pre>
    308   <p>The attributes <code>android:textOn</code> and <code>android:textOff</code> specify the text
    309 for the button when the button has been toggled on or off. The default values are "ON" and
    310 "OFF".</p>
    311 </li>
    312 <li>To do something when the state is changed, add the following code
    313 to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
    314 <pre>
    315 final ToggleButton togglebutton = (ToggleButton) findViewById(R.id.togglebutton);
    316 togglebutton.setOnClickListener(new OnClickListener() {
    317     public void onClick(View v) {
    318         // Perform action on clicks
    319         if (togglebutton.isChecked()) {
    320             Toast.makeText(HelloFormStuff.this, "Checked", Toast.LENGTH_SHORT).show();
    321         } else {
    322             Toast.makeText(HelloFormStuff.this, "Not checked", Toast.LENGTH_SHORT).show();
    323         }
    324     }
    325 });
    326 </pre>
    327 <p>This captures the {@link android.widget.ToggleButton} element from the layout, then adds an
    328 {@link android.view.View.OnClickListener}. The {@link android.view.View.OnClickListener} must
    329 implement the {@link android.view.View.OnClickListener#onClick(View)} callback method, which
    330 defines the action to perform when the button is clicked. In this example, the callback
    331 method checks the new state of the button, then shows a {@link android.widget.Toast} message that
    332 indicates the current state.</p>
    333 
    334 <p>Notice that the {@link android.widget.ToggleButton} handles its own state change between checked
    335 and unchecked, so you just ask which it is.</p>
    336 <li>Run the application.</li>
    337 </ol>
    338 
    339 <p class="note"><strong>Tip:</strong> If you need to change the state
    340 yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}),
    341 use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link
    342 android.widget.CompoundButton#toggle()} method.</p>
    343 
    344 
    345 
    346 
    347 <h2 id="RatingBar">Rating Bar</h2>
    348 
    349 <p>In this section, you'll create a widget that allows the user to provide a rating,
    350 with the {@link android.widget.RatingBar} widget.</p>
    351 
    352 <ol>
    353   <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.RatingBar}
    354 element (inside the {@link android.widget.LinearLayout}):
    355 <pre>
    356     &lt;RatingBar android:id="@+id/ratingbar"
    357         android:layout_width="wrap_content"
    358         android:layout_height="wrap_content"
    359         android:numStars="5"
    360         android:stepSize="1.0"/>
    361 </pre>
    362   <p>The <code>android:numStars</code> attribute defines how many stars to display for the rating
    363 bar. The <code>android:stepSize</code> attribute defines the granularity for each
    364 star (for example, a value of <code>0.5</code> would allow half-star ratings). </p>
    365 </li>
    366 <li>To do something when a new rating has been set, add the following code
    367 to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
    368 <pre>
    369 final RatingBar ratingbar = (RatingBar) findViewById(R.id.ratingbar);
    370 ratingbar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
    371     public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
    372         Toast.makeText(HelloFormStuff.this, "New Rating: " + rating, Toast.LENGTH_SHORT).show();
    373     }
    374 });
    375 </pre>
    376 <p>This captures the {@link android.widget.RatingBar} widget from the layout with {@link
    377 android.app.Activity#findViewById(int)} and then sets an {@link
    378 android.widget.RatingBar.OnRatingBarChangeListener}. The {@link
    379 android.widget.RatingBar.OnRatingBarChangeListener#onRatingChanged(RatingBar,float,boolean)
    380 onRatingChanged()} callback method then defines the action to perform when the user sets a rating.
    381 In this case, a simple {@link android.widget.Toast} message displays the new rating.</p>
    382 
    383 <li>Run the application.</li>
    384 </ol>
    385 
    386 <p>If you've added all the form widgets above, your application should look like this:</p>
    387 <img src="images/hello-formstuff.png" width="150px" />
    388 
    389 <h3>References</h3>
    390 <ul>
    391 	<li>{@link android.widget.ImageButton}</li>
    392 	<li>{@link android.widget.EditText}</li>
    393 	<li>{@link android.widget.CheckBox}</li>
    394 	<li>{@link android.widget.RadioButton}</li>
    395 	<li>{@link android.widget.ToggleButton}</li>
    396   <li>{@link android.widget.RatingBar}</li>
    397 </ul>
    398 
    399