summaryrefslogtreecommitdiffstats
path: root/docs/html/resources/tutorials/views/hello-formstuff.jd
blob: 1ddd1df7fe84431500d1d73ca3393d6baac3d258 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
page.title=Form Stuff
parent.title=Hello, Views
parent.link=index.html
@jd:body

<p>This tutorial introduces a variety of widgets that are useful when creating forms, such as
image buttons, text fields, checkboxes and radio buttons.</p>


<ol>
  <li>Start a new project named <em>HelloFormStuff</em>.</li>
  <li>Your <code>res/layout/main.xml</code> file should already have a basic {@link
android.widget.LinearLayout}:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
&lt;/LinearLayout>
</pre>
    <p>For each widget you want to add, just put the respective View inside this {@link
android.widget.LinearLayout}.</p>
  </li>
</ol>
<p>Each section below also assumes that your <code>HelloFormStuff</code> Activity has the following
default implementation of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:</p>
<pre>
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
}
</pre>

<p>Now select which kind of form widget you'd like to create:</p>
<ul>
  <li><a href="#CustomButton">Custom Button</a></li>
  <li><a href="#EditText">Edit Text</a></li>
  <li><a href="#Checkbox">Checkbox</a></li>
  <li><a href="#RadioButtons">Radio Buttons</a></li>
  <li><a href="#ToggleButton">Toggle Button</a></li>
  <li><a href="#RatingBar">Rating Bar</a></li>
</ul>



<h2 id="CustomButton">Custom Button</h2>

<p>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.</p>

<img src="images/android_pressed.png" style="float:right;" title="android_pressed.png"/>
<img src="images/android_focused.png" style="float:right;clear:right;" title="android_focused.png"/>
<img src="images/android_normal.png" style="float:right;clear:right;" title="android_normal.png"/>
<ol>
  <li>Copy the images on the right into the <code>res/drawable/</code> directory of
your project. These will be used for the different button states.</li>
  <li>Create a new file in the <code>res/drawable/</code> directory named
<code>android_button.xml</code>.
Insert the following XML:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;selector xmlns:android="http://schemas.android.com/apk/res/android">
    &lt;item android:drawable="@drawable/android_pressed"
          android:state_pressed="true" />
    &lt;item android:drawable="@drawable/android_focused"
          android:state_focused="true" />
    &lt;item android:drawable="@drawable/android_normal" />
&lt;/selector>
</pre>
  <p>This defines a single drawable resource, which will change its image based on the current
state of the button. The first <code>&lt;item></code> defines
<code>android_pressed.png</code> as the image when the button is pressed (it's been
activated); the second <code>&lt;item></code> defines <code>android_focused.png</code> as the image
when the button is focused (when the button is highlighted using the trackball or directional
pad); and the third <code>&lt;item></code> defines <code>android_normal.png</code> 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.</p>
  <p class="note"><strong>Note:</strong> The order of the <code>&lt;item></code> elements is
important. When this drawable is referenced, the  <code>&lt;item></code>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 <code>android:state_pressed</code> and
<code>android:state_focused</code> have both evaluated false.</li>
  <li>Open the <code>res/layout/main.xml</code> file and add the {@link
android.widget.Button} element:
<pre>
    &lt;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"/>
</pre>
	<p>The <code>android:background</code> attribute specifies the drawable resource to use for the
button background (which, when saved at <code>res/drawable/android.xml</code>, is
referenced as <code>@drawable/android</code>). This replaces the normal background image
applied by the system with the drawable created above, which changes its image based on
the button state.</p>
    <p>The attribute <code>android:onClick</code> 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.</p>
</li>

<li>To make the button do something when pressed, add the following
method inside your {@link android.app.Activity} class:
<pre>
public void onButtonClicked(View v) {
    // Do something when the button is clicked
    Toast.makeText(HelloFormStuff.this, "Button clicked", Toast.LENGTH_SHORT).show();
}
</pre>
<p>When you specify this kind of method, which is used in your layout file with the {@code
android:onClick} attribute, the method must be <code>public</code>, have a <code>void</code> 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.</p>
</li>
<li>Now run the application.</li>
</ol>



<h2 id="EditText">Edit Text</h2>

<p>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.</p>

<ol>
  <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.EditText}
element (inside the {@link android.widget.LinearLayout}):
<pre>
    &lt;EditText
        android:id="@+id/edittext"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
</pre>
</li>
<li>To do something with the text that the user types, add the following code
to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
<pre>
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) &amp;&amp;
            (keyCode == KeyEvent.KEYCODE_ENTER)) {
          // Perform action on key press
          Toast.makeText(HelloFormStuff.this, edittext.getText(), Toast.LENGTH_SHORT).show();
          return true;
        }
        return false;
    }
});
</pre>
<p>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
<code>true</code> 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).</p>
</li>
<li>Run the application.</li>
</ol>



<h2 id="Checkbox">Checkbox</h2>

<p>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.</p>

<ol>
  <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.CheckBox}
element (inside the {@link android.widget.LinearLayout}):
<pre>
    &lt;CheckBox android:id="@+id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="check it out"
        android:onClick="onCheckboxClicked"/>
</pre>
    <p>The attribute <code>android:onClick</code> 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.</p>
</li>
<li>To do something when the state is changed, add the following method inside your {@link
android.app.Activity} class:</p>

<pre>
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();
    }
}
</pre>

<p>When you specify this kind of method, which is used in your layout file with the {@code
android:onClick}
attribute, the method must be <code>public</code>, have a <code>void</code> 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.</p>
</li>
<li>Run it.</li>
</ol>
<p class="note"><strong>Tip:</strong> 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.</p>



<h2 id="RadioButtons">Radio Buttons</h2>

<p>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.</p>

<ol>
  <li>Open the <code>res/layout/main.xml</code> file and add two {@link
android.widget.RadioButton}s, nested in a {@link android.widget.RadioGroup} (inside the {@link
android.widget.LinearLayout}):
<pre>
    &lt;RadioGroup
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:orientation="vertical">
      &lt;RadioButton android:id="@+id/radio_red"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="Red"
          android:onClick="onRadioButtonClicked"/>
      &lt;RadioButton android:id="@+id/radio_blue"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="Blue"
          android:onClick="onRadioButtonClicked"/>
    &lt;/RadioGroup>
</pre>
<p>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.</p>
    <p>The attribute <code>android:onClick</code> 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.</p>
</li>

<li>To do something when each {@link android.widget.RadioButton} is selected, add the following
method inside your {@link android.app.Activity} class:</p>

<pre>
public void onRadioButtonClicked(View v) {
    // Perform action on clicks
    RadioButton rb = (RadioButton) v;
    Toast.makeText(HelloFormStuff.this, rb.getText(), Toast.LENGTH_SHORT).show();
}
</pre>

<p>When you specify this kind of method, which is used in your layout file with the {@code
android:onClick}
attribute, the method must be <code>public</code>, have a <code>void</code> 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.</p>
<p>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.</p>
</li>
<li>Run the application.</li>
</ol>

<p class="note"><strong>Tip:</strong> 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.</p>



<h2 id="ToggleButton">Toggle Button</h2>

<p>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).</p>

<ol>
  <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.ToggleButton}
element (inside the {@link android.widget.LinearLayout}):
<pre>
    &lt;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"/>
</pre>
  <p>The attributes <code>android:textOn</code> and <code>android:textOff</code> specify the text
for the button when the button has been toggled on or off. The default values are "ON" and
"OFF".</p>
    <p>The attribute <code>android:onClick</code> 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.</p>
</li>
<li>To do something when the user clicks the button, add the following
method inside your {@link android.app.Activity} class:</p>

<pre>
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();
    }
}
</pre>

<p>When you specify this kind of method, which is used in your layout file with the {@code
android:onClick}
attribute, the method must be <code>public</code>, have a <code>void</code> 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.</p>
<p>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.</p>

<p>Notice that the {@link android.widget.ToggleButton} handles its own state change between checked
and unchecked, so you just ask which it is.</p>
<li>Run the application.</li>
</ol>

<p class="note"><strong>Tip:</strong> 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.</p>




<h2 id="RatingBar">Rating Bar</h2>

<p>In this section, you'll create a widget that allows the user to provide a rating,
with the {@link android.widget.RatingBar} widget.</p>

<ol>
  <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.RatingBar}
element (inside the {@link android.widget.LinearLayout}):
<pre>
    &lt;RatingBar android:id="@+id/ratingbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:numStars="5"
        android:stepSize="1.0"/>
</pre>
  <p>The <code>android:numStars</code> attribute defines how many stars to display for the rating
bar. The <code>android:stepSize</code> attribute defines the granularity for each
star (for example, a value of <code>0.5</code> would allow half-star ratings). </p>
</li>
<li>To do something when a new rating has been set, add the following code
to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
<pre>
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();
    }
});
</pre>
<p>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.</p>

<li>Run the application.</li>
</ol>

<p>If you've added all the form widgets above, your application should look like this:</p>
<img src="images/hello-formstuff.png" width="150px" />

<h3>References</h3>
<ul>
	<li>{@link android.widget.ImageButton}</li>
	<li>{@link android.widget.EditText}</li>
	<li>{@link android.widget.CheckBox}</li>
	<li>{@link android.widget.RadioButton}</li>
	<li>{@link android.widget.ToggleButton}</li>
  <li>{@link android.widget.RatingBar}</li>
</ul>