From 5615ca1979caa79041bf16a2cae49f9cfadd7ee5 Mon Sep 17 00:00:00 2001
From: Scott Main {@link android.widget.AutoCompleteTextView} is an implementation of the EditText widget that will provide
-auto-complete suggestions as the user types. The suggestions are extracted from a collection of strings. To create a text entry widget that provides auto-complete suggestions, use
+the {@link android.widget.AutoCompleteTextView} widget. Suggestions are received from a
+collection of strings associated with the widget through an {@link
+android.widget.ArrayAdapter}. In this tutorial, you will create a {@link android.widget.AutoCompleteTextView} widget that
+provides suggestions for a country name. This file defines a simple {@link android.widget.TextView} that will be used for each
+item that appears in the list of suggestions. The {@link android.widget.TextView} is a label that introduces the {@link
+android.widget.AutoCompleteTextView} widget.
Here, we create an AutoComplteteTextView from our layout. We then
- create an {@link android.widget.ArrayAdapter} that binds a After the content view is set to the This is the list of suggestions that will be offered as the user types into the
- AutoCompleteTextView. This is the list of suggestions that will be provided in a drop-down list when the user types into
+the {@link android.widget.AutoCompleteTextView} widget. As you type, you should see something like this: Note that using a hard-coded string array is not a recommended design practice because your
+application code should focus on behavior, not content. Application content such as strings
+should be externalized from the code in order to make modifications to the content easier and
+facilitate localization of the content. The hard-coded strings are used in this tutorial only to
+make it simple and focus on the {@link android.widget.AutoCompleteTextView} widget.
+Instead, your application should declare such string arrays in an XML file. This can be done
+with a {@code <string-array<} resource in your project {@code res/values/strings.xml} file.
+For example: To use these resource strings for the {@link android.widget.ArrayAdapter}, replace the original
+{@link android.widget.ArrayAdapter} constructor line with the following: A {@link android.widget.DatePicker} is a widget that allows the user to select a month, day and year. To provide a widget for selecting a date, use the {@link android.widget.DatePicker}
+widget, which allows the user to select the month, day, and year, in a familiar interface. In this tutorial, you'll create a {@link android.app.DatePickerDialog}, which presents the
+date picker in a floating dialog box at the press of a button. When the date is set by
+the user, a {@link android.widget.TextView} will update with the new date. For the layout, we're using a vertical LinearLayout, with a {@link android.widget.TextView} that
- will display the date and a {@link android.widget.Button} that will initiate the DatePicker dialog.
- With this layout, the TextView will sit above the Button.
- The text value in the TextView is set empty, as it will be filled
- with the current date when our Activity runs. This creates a basic {@link android.widget.LinearLayout} with a {@link android.widget.TextView}
+ that will display the date and a {@link android.widget.Button} that will open the {@link
+ android.app.DatePickerDialog}. The first group of members define variables for the layout {@link android.view.View}s and the
+date items. The Tip: Press Ctrl(or Cmd) + Shift + O to import all needed packages. We start by instantiating variables for our Views and date fields.
- The This method is passed the identifier we gave First, the content is set to the This uses the member date values to write the date to our TextView. This method uses the member date values declared for the class to write the date to the layout's
+{@link android.widget.TextView}, {@code mDateDisplay}, which was also declared and initialized
+above. This The {@link android.app.DatePickerDialog.OnDateSetListener} listens for when the user
+has set the date (by clicking the "Set" button). At that time, the {@link
+android.app.DatePickerDialog.OnDateSetListener#onDateSet(DatePicker,int,int,int) onDateSet()}
+callback method is called, which is defined to update the {@code mYear}, {@code mMonth}, and
+{@code mDay} member fields with the new date then call the private This is an {@link android.app.Activity} callback method that is passed the integer ID given to
+{@link android.app.Activity#showDialog(int)} (which is called by the button's {@link
+android.view.View.OnClickListener}). When the ID matches the switch case defined here, a {@link
+android.app.DatePickerDialog} is instantiated with the {@link
+android.app.DatePickerDialog.OnDateSetListener} created in the previous
+step, along with the date variables to initialize the widget date. When you press the "Change the date" button, you should see the following: This page introduces a variety of widgets, like image buttons,
-text fields, checkboxes and radio buttons. This tutorial introduces a variety of widgets that are useful when creating forms, such as
+image buttons, text fields, checkboxes and radio buttons. For each widget you want to add, just put the respective View inside here. For each widget you want to add, just put the respective View inside this {@link
+android.widget.LinearLayout}. Tip: As you add new Android code, press Ctrl(or Cmd) + Shift + O
-to import all needed packages. Each section below also assumes that your A button with a custom image on it.
-We'll make it display a message when pressed. 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. The source of the button
- is from the res/drawable/ directory, where we've placed the android.png. Tip: You can also reference some of the many built-in
- images from the Android {@link android.R.drawable} resources,
- like This defines a single drawable resource, which will change its image based on the current
+state of the button. The first Note: The order of the The This captures our ImageButton from the layout, then adds an on-click listener to it.
-The {@link android.view.View.OnClickListener} must define the This captures the {@link android.widget.Button} from the layout, then adds an {@link
+android.view.View.OnClickListener}. The {@link android.view.View.OnClickListener}
+must implement the {@link android.view.View.OnClickListener#onClick(View)} callback method, which
+defines the action to be made when the button is clicked. In this example, a
+{@link android.widget.Toast} message will be displayed. A text field for user input. We'll make it display the text entered so far when the "Enter" key is pressed. 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. This captures our EditText element from the layout, then adds an on-key listener to it.
-The {@link android.view.View.OnKeyListener} must define the 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
+ A checkbox for selecting items. We'll make it display the the current state when pressed. 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. This captures our CheckBox element from the layout, then adds an on-click listener to it.
-The {@link android.view.View.OnClickListener} must define the This captures the {@link android.widget.CheckBox} element from the layout, then adds an {@link
+android.view.View.OnClickListener}. The {@link android.view.View.OnClickListener} must implement the
+{@link android.view.View.OnClickListener#onClick(View)} callback method, which
+defines the action to be made when the checkbox is clicked. When clicked, {@link
+android.widget.CompoundButton#isChecked()} is called to check the new state of the check box. If it
+has been checked, then a {@link android.widget.Toast} displays the message "Selected", otherwise it
+displays "Not selected". Note that the {@link android.view.View} object that is passed in the {@link
+android.view.View.OnClickListener#onClick(View)} callback must be cast to a {@link
+android.widget.CheckBox} because the {@link android.widget.CompoundButton#isChecked()} method is
+not defined by the parent {@link android.view.View} class. The {@link android.widget.CheckBox}
+handles its own state changes, so you only need to query the current state. Tip: If you find that you need to change the state
-in another way (such as when loading a saved {@link android.preference.CheckBoxPreference}),
-use 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. Two mutually-exclusive radio buttons—enabling one disables the other.
-When each is pressed, we'll pop up a message. 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. 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. Our First, the {@link android.view.View} that is passed to the {@link
+android.view.View.OnClickListener#onClick(View)} method is cast into a RadioButton. Then a
+{@link android.widget.Toast} message displays the selected radio button's text. This captures each of the RadioButtons from our layout and adds the newly-created
-OnClickListener to each. This captures each of the {@link android.widget.RadioButton}s from the layout and adds the
+newly-created {@link android.view.View.OnClickListener} to each. Tip: If you find that you need to change the state of a
-RadioButton in another way (such as when loading a saved {@link android.preference.CheckBoxPreference}),
-use 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. A button used specifically for toggling something on and off. 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). The attributes This captures our ToggleButton element from the layout, then adds an on-click listener to it.
-The {@link android.view.View.OnClickListener} must define the This captures the {@link android.widget.ToggleButton} element from the layout, then adds an
+{@link android.view.View.OnClickListener}. The {@link android.view.View.OnClickListener} must
+implement the {@link android.view.View.OnClickListener#onClick(View)} callback method, which
+defines the action to perform when the button is 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: By default, the text on the button is "ON" and "OFF", but
-you can change each of these with 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. The 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 items above, your application should look something like this: If you've added all the form widgets above, your application should look like this:
-
list_item.xml and save it inside the
+res/layout/ folder. Edit the file to look like this:
+
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:textSize="16sp"
+ android:textColor="#000">
+</TextView>
+
+ res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
- android:layout_height="wrap_content">
-
+ android:layout_height="wrap_content"
+ android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Country" />
-
- <AutoCompleteTextView android:id="@+id/edit"
+ <AutoCompleteTextView android:id="@+id/autocomplete_country"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
-
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="5dp"/>
</LinearLayout>
+ onCreate method:
+HelloAutoComplete.java and insert the following code for the {@link
+android.app.Activity#onCreate(Bundle) onCreate()} method:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
- AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit);
- ArrayAdapter
- simple_dropdown_item_1line
- layout item to each entry in the COUNTRIES array (which we'll add next).
- The last part sets the ArrayAdapter to associate with our AutoCompleteTextView.main.xml layout, the {@link
+android.widget.AutoCompleteTextView} widget is captured from the layout with {@link
+android.app.Activity#findViewById(int)}. A new {@link
+android.widget.ArrayAdapter} is then initialized to bind the list_item.xml layout
+to each list item in the COUNTRIES string array (defined in the next step).
+Finally, {@link android.widget.AutoCompleteTextView#setAdapter(T) setAdapter()} is called to
+associate the {@link android.widget.ArrayAdapter} with the
+{@link android.widget.AutoCompleteTextView} widget so that the string array will populate
+the list of suggestions.onCreate() method, add the String array:
+HelloAutoComplete class, add the string array:
static final String[] COUNTRIES = new String[] {
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
@@ -96,19 +122,50 @@ static final String[] COUNTRIES = new String[] {
"Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
};
-
+More Information
+
+
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string-array name="countries_array">
+ <item>Bahrain</item>
+ <item>Bangladesh</item>
+ <item>Barbados</item>
+ <item>Belarus</item>
+ <item>Belgium</item>
+ <item>Belize</item>
+ <item>Benin</item>
+ </string-array>
+</resources>
+
+
+String[] countries = getResources().getStringArray(R.array.countries_array);
+ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, countries);
+
+
+
References
-
diff --git a/docs/html/resources/tutorials/views/hello-datepicker.jd b/docs/html/resources/tutorials/views/hello-datepicker.jd
index fcd43f3..c50d650 100644
--- a/docs/html/resources/tutorials/views/hello-datepicker.jd
+++ b/docs/html/resources/tutorials/views/hello-datepicker.jd
@@ -1,52 +1,57 @@
-page.title=Hello, DatePicker
+page.title=Date Picker
parent.title=Hello, Views
parent.link=index.html
@jd:body
-
-
+
res/layout/main.xml file and insert the following:
+
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
-
<TextView android:id="@+id/dateDisplay"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text=""/>
-
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text=""/>
<Button android:id="@+id/pickDate"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Change the date"/>
-
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Change the date"/>
</LinearLayout>
- HelloDatePicker.java and add the following members to the class:
private TextView mDateDisplay;
private Button mPickDate;
-
private int mYear;
private int mMonth;
private int mDay;
static final int DATE_DIALOG_ID = 0;
+
+ DATE_DIALOG_ID is a static integer that uniquely identifies the {@link
+android.app.Dialog} that will display the date picker.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
@@ -68,43 +73,30 @@ parent.link=index.html
mMonth = c.get(Calendar.MONTH);
mDay = c.get(Calendar.DAY_OF_MONTH);
- // display the current date
+ // display the current date (this method is below)
updateDisplay();
}
-DATE_DIALOG_ID is a static integer that uniquely identifies the Dialog. In the
- onCreate() method, we get prepared by setting the layout and capturing the View elements.
- Then we create an on-click listener for the Button, so that when it is clicked it will
- show our DatePicker dialog. The showDialog() method will pop-up the date picker dialog
- by calling the onCreateDialog() callback method
- (which we'll define in the next section). We then create an
- instance of {@link java.util.Calendar} and get the current year, month and day. Finally, we call
- updateDisplay()—our own method (defined later) that will fill the TextView.onCreate() method, add the onCreateDialog() callback method
-(which is called by showDialog())
-
-@Override
-protected Dialog onCreateDialog(int id) {
- switch (id) {
- case DATE_DIALOG_ID:
- return new DatePickerDialog(this,
- mDateSetListener,
- mYear, mMonth, mDay);
- }
- return null;
-}
-
- showDialog() and initializes
- the DatePicker to the date we retrieved from our Calendar instance.main.xml layout. Then the {@link
+android.widget.TextView} and {@link android.widget.Button} elements are captured from the layout
+with {@link android.app.Activity#findViewById(int)}. A
+new {@link android.view.View.OnClickListener} is created for the
+{@link android.widget.Button}, so that when it is clicked, it
+will call {@link android.app.Activity#showDialog(int)}, passing the unique integer ID for
+the date picker dialog. Using {@link android.app.Activity#showDialog(int)} allows the {@link
+android.app.Activity} to manage the life-cycle of the dialog and will call the {@link
+android.app.Activity#onCreateDialog(int)} callback method to request the {@link android.app.Dialog}
+that should be displayed (which you'll
+define later). After the on-click listener is set, a new {@link java.util.Calendar} is created
+and the current year, month and day are acquired. Finally, the private
+updateDisplay() method is called in order to fill the {@link android.widget.TextView}
+with the current date.updateDisplay() method:
+updateDisplay() method:
- // updates the date we display in the TextView
+ // updates the date in the TextView
private void updateDisplay() {
mDateDisplay.setText(
new StringBuilder()
@@ -114,9 +106,13 @@ protected Dialog onCreateDialog(int id) {
.append(mYear).append(" "));
}
-HelloDatePicker class:
// the callback received when the user "sets" the date in the dialog
private DatePickerDialog.OnDateSetListener mDateSetListener =
@@ -131,19 +127,45 @@ protected Dialog onCreateDialog(int id) {
}
};
- OnDateSetListener method listens for when the user is done setting the date
- (clicks the "Set" button). At that time, this fires and we update our member fields with
- the new date defined by the user and update our TextView by calling updateDisplay().updateDisplay()
+method to update the {@link android.widget.TextView}.
+@Override
+protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DATE_DIALOG_ID:
+ return new DatePickerDialog(this,
+ mDateSetListener,
+ mYear, mMonth, mDay);
+ }
+ return null;
+}
+
+
References
-
-
-
+
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>
- 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);
+}
+
+
+
+Custom Button
-ImageButton
-
+
+
-
- Drag the Android image on the right (or your own image) into the
- res/drawable/ directory of your project.
- We'll use this for the button.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:
-<ImageButton
- android:id="@+id/android_button"
- android:layout_width="100dip"
- android:layout_height="wrap_content"
- android:src="@drawable/android" />
+<?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>
- ic_media_play, for a "play" button image. To do so, change the source
- attribute to android:src="@android:drawable/ic_media_play".<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.<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: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
+used for buttons throughout the system. In order for the drawable to change its image based on
+the button state, the image must be applied to the background.onCreate() method:
+
+
-final ImageButton button = (ImageButton) findViewById(R.id.android_button);
+final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Perform action on clicks
@@ -60,34 +101,41 @@ button.setOnClickListener(new OnClickListener() {
}
});
-onClick() method, which
-defines the action to be made when the button is clicked. Here, we show a
-{@link android.widget.Toast} message when clicked.EditText
-
-
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"/>
+ <EditText
+ android:id="@+id/edittext"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
onCreate() method:
+
final EditText edittext = (EditText) findViewById(R.id.edittext);
edittext.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
- if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
+ // 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;
@@ -96,37 +144,44 @@ edittext.setOnKeyListener(new OnKeyListener() {
}
});
-onKey() method, which
-defines the action to be made when a key is pressed. In this case, we want to listen for the
-Enter key (when pressed down), then pop up a {@link android.widget.Toast} message with the
-text from the EditText field. Be sure to return true after the event is handled,
-so that the event doesn't bubble-up and get handled by the View (which would result in a
-carriage return in the text field).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).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" />
+ <CheckBox android:id="@+id/checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="check it out" />
onCreate() method:
+to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
final CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox);
checkbox.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- // Perform action on clicks
- if (checkbox.isChecked()) {
+ // 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();
@@ -134,52 +189,62 @@ checkbox.setOnClickListener(new OnClickListener() {
}
});
-onClick() method, which
-defines the action to be made when the checkbox is clicked. Here, we query the current state of the
-checkbox, then pop up a {@link android.widget.Toast} message that displays the current state.
-Notice that the CheckBox handles its own state change between checked and un-checked, so we just
-ask which it currently is.setChecked(true) or toggle().RadioButton
-
-
-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" />
-
- <RadioButton android:id="@+id/radio_blue"
- android:layout_width="wrap_content"
+ <RadioGroup
+ android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:text="Blue" />
-
-</RadioGroup>
+ android:orientation="vertical">
+ <RadioButton android:id="@+id/radio_red"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Red" />
+ <RadioButton android:id="@+id/radio_blue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Blue" />
+ </RadioGroup>
+onCreate() method):
+
+HelloFormStuff Activity:
-OnClickListener radio_listener = new OnClickListener() {
+private OnClickListener radio_listener = new OnClickListener() {
public void onClick(View v) {
// Perform action on clicks
RadioButton rb = (RadioButton) v;
@@ -187,68 +252,124 @@ OnClickListener radio_listener = new OnClickListener() {
}
};
-onClick() method will be handed the View clicked, so the first thing to do
-is cast it into a RadioButton. Then we pop up a
-{@link android.widget.Toast} message that displays the selection.onCreate() method, add the following:
+
final RadioButton radio_red = (RadioButton) findViewById(R.id.radio_red);
final RadioButton radio_blue = (RadioButton) findViewById(R.id.radio_blue);
radio_red.setOnClickListener(radio_listener);
radio_blue.setOnClickListener(radio_listener);
-setChecked(true) or toggle().ToggleButton
-
-
-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" />
+ <ToggleButton android:id="@+id/togglebutton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textOn="Vibrate on"
+ android:textOff="Vibrate off"/>
+ 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".onCreate() method:
+to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
final ToggleButton togglebutton = (ToggleButton) findViewById(R.id.togglebutton);
togglebutton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Perform action on clicks
if (togglebutton.isChecked()) {
- Toast.makeText(HelloFormStuff.this, "ON", Toast.LENGTH_SHORT).show();
+ Toast.makeText(HelloFormStuff.this, "Checked", Toast.LENGTH_SHORT).show();
} else {
- Toast.makeText(HelloFormStuff.this, "OFF", Toast.LENGTH_SHORT).show();
+ Toast.makeText(HelloFormStuff.this, "Not checked", Toast.LENGTH_SHORT).show();
}
}
});
-onClick() method, which
-defines the action to be made when the button is clicked. Here, we query the current state of the
-ToggleButton, then pop up a {@link android.widget.Toast} message that displays the current state.
-Notice that the ToggleButton handles its own state change between checked and un-checked, so we just
-ask which it is.setTextOn(CharSequence) and
-setTextOff(CharSequence). And, if you find that you need to change the state
-in another way (such as when loading a saved {@link android.preference.CheckBoxPreference}),
-use setChecked(true) or toggle(). RatingBar
+
+
+
-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"/>
+
+ 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();
+ }
+});
+
+
References
@@ -258,5 +379,6 @@ use setChecked(true) or toggle().
A {@link android.widget.Gallery} is a View commonly used to display items in a horizontally scrolling list -that locks the current selection at the center. When one is selected, we'll show a message.
+{@link android.widget.Gallery} is a layout widget used to display items in a +horizontally scrolling list and positions the current selection at the center of the view.
+ +In this tutorial, you'll create a gallery of photos and then display a toast message each time a +gallery item is selected.
res/drawable/ directory.res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?>
<Gallery xmlns:android="http://schemas.android.com/apk/res/android"
@@ -19,10 +24,10 @@ that locks the current selection at the center. When one is selected, we'll show
android:layout_height="wrap_content"
/>
-onCreate() method:
+HelloGallery.java file and insert the following code for the
+{@link android.app.Activity#onCreate(Bundle) onCreate()} method:
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -39,19 +44,46 @@ public void onCreate(Bundle savedInstanceState) {
});
}
- We start as usual: set the layout and capture the View we want (our Gallery).
-We then set an Adapter, called ImageAdapter for the Gallery—this is a new class that
-we'll create next. Then we create an item click listener for the Gallery. This is like a normal
-on-click listener (which you might be familiar with for buttons), but it listens to each item
-that we've added to the Gallery. The onItemClick() callback method
-receives the AdapterView where the click occurred, the specific View that received the click, the
-position of the View clicked (zero-based), and the row id of the item clicked (if applicable). All
-that we care about is the position, so that we can pop up a {@link android.widget.Toast} message that
-tells us the index position of the item clicked. We do this with Toast.makeText().show().
+
This starts by setting the {@code main.xml} layout as the content view and then capturing the
+{@link android.widget.Gallery} from
+the layout with {@link
+android.app.Activity#findViewById(int)}. A custom {@link android.widget.BaseAdapter} called
+ImageAdapter is
+instantiated and applied to the {@link android.widget.Gallery} with {@link
+android.widget.AdapterView#setAdapter(T) setAdapter()}. (The ImageAdapter class is
+defined next.)
+Then an anonymous {@link android.widget.AdapterView.OnItemClickListener} is instantiated. The
+{@link android.widget.AdapterView.OnItemClickListener#onItemClick(AdapterView,View,int,long)}
+callback method receives the {@link android.widget.AdapterView} where the click occurred, the
+specific {@link android.view.View} that received the click, the
+position of the {@link android.view.View} clicked (zero-based), and the row ID of the item clicked
+(if applicable). In this example, all that's needed is the position of the click to show a {@link
+android.widget.Toast} message that says the position of the item, using
+{@link android.widget.Toast#makeText(Context,CharSequence,int)} and {@link
+android.widget.Toast#show()} (in a real world scenario, this ID could be used to get the full sized
+image for some other task).
onCreate() method, add the ImageAdapter class:
+ res/values/ directory named attrs.xml.
+Insert the following:
++<?xml version="1.0" encoding="utf-8"?> +<resources> + <declare-styleable name="HelloGallery"> + <attr name="android:galleryItemBackground" /> + </declare-styleable> +</resources> ++
This is a custom styleable resource that can be applied to a layout. In this case, it will be
+applied to the individual items placed into the {@link android.widget.Gallery} widget. The
+<attr> element defines a specific attribute for the styleable, and in this case, it
+refers to an existing platform attribute, {@link android.R.attr#galleryItemBackground}, which
+defines a border styling for gallery items. In the next step, you'll
+see how this attribute is referenced and then later applied to each item in the gallery.
HelloGallery.java file. After the {@link
+ android.app.Activity#onCreate(Bundle)} method, define the custom ImageAdapter class:
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
@@ -100,26 +132,30 @@ public class ImageAdapter extends BaseAdapter {
}
First, there are a few member variables, including an array of IDs that reference -the images we placed in our drawable resources directory.
-Next is the constructor, where we define the member Context. The rest of the constructor
-sets up a reference for our Gallery them, which adds the nice framing for each Gallery item.
-Once we have our mGalleryItemBackground, it's important to recycle the
-StyledAttribute for later re-use.
The next three methods are required for basic member queries.
-But then we have the getView() method, which is called
-for each item read by our ImageAdapter, when the Gallery is being built. Here, we
-use our member Context to create a new {@link android.widget.ImageView}. We then define
-the image resource with the current position of the Gallery items (corresponding to our
-array of drawables), set the dimensions for the ImageView,
-set the image scaling to fit the ImageView dimensions, then finally set the
-background theme for the ImageView.
See {@link android.widget.ImageView.ScaleType} -for other image scaling options, in case you want to avoid stretching images that don't -exactly match the ImageView dimensions.
- -Next is the class constructor, where the {@link android.content.Context} for an {@code +ImageAdapter} instance is defined and the styleable +resource defined in the last step is acquired and saved to a local field. At the end of the +constructor, {@link android.content.res.TypedArray#recycle()} is called on the {@link +android.content.res.TypedArray} so it can be re-used by the system.
+The methods {@link android.widget.Adapter#getCount()}, {@link +android.widget.Adapter#getItem(int)}, and {@link android.widget.Adapter#getItemId(int)} are methods +that must be implemented for simple queries on the {@link android.widget.Adapter}. +The {@link android.widget.Adapter#getView(int,View,ViewGroup) method does the +work to apply an image to an {@link android.widget.ImageView} that will be embedded in the +{@link android.widget.Gallery}. In this method, the member {@link android.content.Context} is used +to create a new {@link android.widget.ImageView}. The {@link android.widget.ImageView} is prepared +by applying an image from the local array of drawable resources, setting the {@link +android.widget.Gallery.LayoutParams} height and width for the image, setting the scale to fit the +{@link android.widget.ImageView} dimensions, and then finally setting the background to use the +styleable attribute acquired in the constructor.
+ +See {@link android.widget.ImageView.ScaleType} for other image scaling options.
+ + +You should see something like this:
@@ -129,7 +165,7 @@ exactly match the ImageView dimensions.
A {@link android.widget.GridView} displays items in a two-dimensional, scrolling grid. The items -are acquired from a {@link android.widget.ListAdapter}.
+{@link android.widget.GridView} is a {@link android.view.ViewGroup} that displays items in a +two-dimensional, +scrollable grid. The grid items are automatically inserted to the layout using a {@link +android.widget.ListAdapter}.
+ +In this tutorial, you'll create a grid of image thumbnails. When an item is selected, a +toast message will display the position of the image.
res/drawable/ directory.res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
+ android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
- android:columnWidth="90dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>
+ This {@link android.widget.GridView} will fill the entire screen. The attributes are rather +self explanatory. For more information about valid attributes, see the {@link +android.widget.GridView} reference.
onCreate() method:
+ HelloGridView.java and insert the following code for the
+{@link android.app.Activity#onCreate(Bundle) onCreate()} method:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -35,12 +46,33 @@ public void onCreate(Bundle savedInstanceState) {
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
+
+ gridview.setOnItemClickListener(new OnItemClickListener() {
+ public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
+ Toast.makeText(HelloGridView.this, "" + position, Toast.LENGTH_SHORT).show();
+ }
+ });
}
- Here, we get a handle on our GridView, from the layout, and give it an Adapter. - We're actually going to create our own Adapter called ImageAdapter.
+After the {@code main.xml} layout is set for the content view, the +{@link android.widget.GridView} is captured from the layout with {@link +android.app.Activity#findViewById(int)}. The {@link +android.widget.GridView#setAdapter(T) setAdapter()} method then sets a custom adapter ({@code +ImageAdapter}) as the source for all items to be displayed in the grid. The {@code ImageAdapter} is +created in the next step.
+To do something when an item in the grid is clicked, the {@link +android.widget.AdapterView#setOnItemClickListener(OnItemClickListener) setOnItemClickListener()} +method is passed a new {@link android.widget.AdapterView.OnItemClickListener}. This anonymous +instance defines the {@link +android.widget.AdapterView.OnItemClickListener#onItemClick(AdapterView,View,int,long) +onItemClick()} callback method to show a {@link android.widget.Toast} that displays the index +position (zero-based) of the selected item (in a real world scenario, the position could be used to +get the full sized +image for some other task).
+ImageAdapter that extends {@link
+android.widget.BaseAdapter}:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
@@ -93,37 +125,58 @@ public class ImageAdapter extends BaseAdapter {
};
}
- First we take care of some required methods inherited from BaseAdapter.
- The constructor and getCount() are self-explanitory. Normally, getItem()
- should return the actual object at the specified position in our Adapter, but for this Hello World,
- we're not going to bother. Likewise, getItemId() should return the row id of
- the item, but right now we don't care.
However, getView() is the method we care about. This one creates a new View for each image that we
- put in our ImageAdapter. So we're going to create an ImageView each time. When this is called, we're
- going to receive a View, which is likely a recycled View object (at least after the first call), so we
- check for this—if it's null, we initialize the ImageView and setup all the properties we want.
- The LayoutParams() initialization sets the height and width of the View—this ensures
- that no matter the drawable size, each image is resized and cropped to fit in the ImageView (if necessary).
- With setScaleType(), we say that images should be cropped toward the center (if necessary).
- And finally, we set the padding within the ImageView. (Note that, if the images have various aspect-ratios,
- as they do in this demo, then less padding will cause for more cropping of the image, if it does not match
- the dimensions given to the ImageView.) At the end of getView() we set the image resource and
- return the ImageView.
All that's left is our array or drawable resources at the bottom.
+First, this implements some required methods inherited from {@link +android.widget.BaseAdapter}. The constructor and {@link +android.widget.Adapter#getCount()} are self-explanatory. Normally, {@link +android.widget.Adapter#getItem(int)} should return the actual object at the specified position in +the adapter, but it's ignored for this example. Likewise, {@link +android.widget.Adapter#getItemId(int)} should return the row id of the item, but it's not +needed here.
+ +The first method necessary is {@link android.widget.Adapter#getView(int,View,ViewGroup) +getView()}. This method creates a new {@link android.view.View} for each image added to the {@code +ImageAdapter}. When this is called, a {@link android.view.View} is passed in, which is normally a +recycled object (at least after this has been called once), so there's a check to see if the +object is null. If it is null, an {@link android.widget.ImageView} is instantiated and +configured with desired properties for the image presentation:
+If the {@link android.view.View} passed to {@link +android.widget.Adapter#getView(int,View,ViewGroup) getView()} is not null, then the local +{@link android.widget.ImageView} is initialized with the recycled {@link android.view.View} +object.
+ +At the end of the {@link android.widget.Adapter#getView(int,View,ViewGroup) getView()} method, +the {@code +position} integer passed into the method is used to select an image from the {@code mThumbIds} +array, which is set as the image resource for the {@link android.widget.ImageView}.
+All that's left is to define the {@code mThumbIds} array of drawable resources.
Your grid layout should look something like this:
-Try experimenting with the behaviors of the GridView and ImageView by adjusting their properties. For example, - instead of setting the ImageView LayoutParams, you can try using - {@link android.widget.ImageView#setAdjustViewBounds(boolean)}.
+Try experimenting with the behaviors of the {@link android.widget.GridView} and {@link +android.widget.ImageView} elements by adjusting their properties. For example, instead of using +{@link android.view.View#setLayoutParams(ViewGroup.LayoutParams)}, try using +{@link android.widget.ImageView#setAdjustViewBounds(boolean)}.
A {@link android.widget.LinearLayout} is a GroupView that will lay child View elements -vertically or horizontally.
+{@link android.widget.LinearLayout} is a {@link android.view.ViewGroup} that displays child +{@link android.view.View} elements in a linear direction, either vertically or horizontally.
+You should be careful about over-using the {@link android.widget.LinearLayout}. If you begin +nesting multiple {@link android.widget.LinearLayout}s, you may want to consider using a {@link +android.widget.RelativeLayout} instead.
res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -18,113 +20,114 @@ vertically or horizontally.
android:layout_width="fill_parent"
android:layout_height="fill_parent">
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_weight="1">
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1">
+ <TextView
+ android:text="red"
+ android:gravity="center_horizontal"
+ android:background="#aa0000"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"/>
+ <TextView
+ android:text="green"
+ android:gravity="center_horizontal"
+ android:background="#00aa00"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"/>
+ <TextView
+ android:text="blue"
+ android:gravity="center_horizontal"
+ android:background="#0000aa"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"/>
+ <TextView
+ android:text="yellow"
+ android:gravity="center_horizontal"
+ android:background="#aaaa00"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"/>
+ </LinearLayout>
- <TextView
- android:text="red"
- android:gravity="center_horizontal"
- android:background="#aa0000"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_weight="1"/>
-
- <TextView
- android:text="green"
- android:gravity="center_horizontal"
- android:background="#00aa00"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_weight="1"/>
-
- <TextView
- android:text="blue"
- android:gravity="center_horizontal"
- android:background="#0000aa"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_weight="1"/>
-
- <TextView
- android:text="yellow"
- android:gravity="center_horizontal"
- android:background="#aaaa00"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_weight="1"/>
-
- </LinearLayout>
-
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_weight="1">
-
- <TextView
- android:text="row one"
- android:textSize="15pt"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
-
- <TextView
- android:text="row two"
- android:textSize="15pt"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
-
- <TextView
- android:text="row three"
- android:textSize="15pt"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
-
- <TextView
- android:text="row four"
- android:textSize="15pt"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
-
- </LinearLayout>
-
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1">
+ <TextView
+ android:text="row one"
+ android:textSize="15pt"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+ <TextView
+ android:text="row two"
+ android:textSize="15pt"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+ <TextView
+ android:text="row three"
+ android:textSize="15pt"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+ <TextView
+ android:text="row four"
+ android:textSize="15pt"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+ </LinearLayout>
+
</LinearLayout>
- Carefully inspect the XML. You'll notice how this layout works a lot like - an HTML layout. There is one parent LinearLayout that is defined to lay - its child elements vertically. The first child is another LinearLayout that uses a horizontal layout - and the second uses a vertical layout. Each LinearLayout contains several {@link android.widget.TextView} - elements.
+ +Carefully inspect this XML. There is a root {@link android.widget.LinearLayout} that defines +its orientation to be vertical—all child {@link android.view.View}s (of which it has two) will +be stacked vertically. The first child is +another {@link android.widget.LinearLayout} that uses a horizontal orientation and the second child +is a {@link android.widget.LinearLayout} that uses a vertical orientation. Each of these nested +{@link android.widget.LinearLayout}s contain several {@link android.widget.TextView} elements, which +are oriented with each other in the manner defined by their parent {@link +android.widget.LinearLayout}.
onCreate() method:
+HelloLinearLayout.java and be sure it loads the
+res/layout/main.xml layout in the
+{@link android.app.Activity#onCreate(Bundle) onCreate()} method:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
-R.layout.main refers to the main.xml layout file.
The {@link android.app.Activity#setContentView(int)} method loads the
+layout file for the {@link android.app.Activity}, specified by the resource
+ID — R.layout.main refers to the res/layout/main.xml layout
+file.
You should see the following:
-Notice how the various XML attributes define the View's behavior.
-Pay attention to the effect of the layout_weight. Try
- experimenting with different values to see how the screen real estate is
- distributed based on the weight of each element.
Notice how the XML attributes define each View's behavior. Try
+experimenting with different values for android:layout_weight to see how the screen
+real estate is distributed based on the weight of each element. See the Common Layout Objects
+document for more about how {@link android.widget.LinearLayout} handles the
+android:layout_weight attribute.
A {@link android.widget.ListView} is a View that shows items in a vertically scrolling list. The items are - acquired from a {@link android.widget.ListAdapter}.
+{@link android.widget.ListView} is a {@link android.view.ViewGroup} that creates a list of +scrollable items. The list items are automatically inserted to the list using a {@link +android.widget.ListAdapter}.
+In this tutorial, you'll create a scrollable list of country names that are read from a string array. +When a list item is selected, a toast message will display the position of the item in the list.
list_item.xml and save it inside the
+res/layout/ folder. Insert the following:
++<?xml version="1.0" encoding="utf-8"?> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:padding="10dp" + android:textSize="16sp" > +</TextView> ++
This file defines the layout for each item that will be placed in the {@link +android.widget.ListView}.
+HelloListView.java and make the class extend {@link
+android.app.ListActivity} (instead of {@link android.app.Activity}):
public class HelloListView extends ListActivity {
onCreate() method:
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- setListAdapter(new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1, COUNTRIES));
- getListView().setTextFilterEnabled(true);
+
+ setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, COUNTRIES));
+
+ ListView lv = getListView();
+ lv.setTextFilterEnabled(true);
+
+ lv.setOnItemClickListener(new OnItemClickListener() {
+ public void onItemClick(AdapterView<?> parent, View view,
+ int position, long id) {
+ // When clicked, show a toast with the TextView text
+ Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
+ Toast.LENGTH_SHORT).show();
+ }
+ });
}
- Notice that we don't need to load a layout (at least, not in this case, because we're using
- the whole screen for our list). Instead, we just call setListAdapter() (which automatically
- adds a ListView to the ListActivity), and provide it with an ArrayAdapter that binds a
- simple_list_item_1 layout item to each entry in the COUNTRIES
- array (added next). The next line of code adds a text filter to the ListView, so that when the user
- begins typing, the list will filter the entire view to display only the items that match the entry.
onCreate() method, add the String array:
+Notice that this does not load a layout file for the Activity (which you usually do with {@link +android.app.Activity#setContentView(int)}). Instead, {@link +android.app.ListActivity#setListAdapter(ListAdapter)} automatically +adds a {@link android.widget.ListView} to fill the entire screen of the {@link +android.app.ListActivity}. This method takes an {@link android.widget.ArrayAdapter}, which +manages the array of list items that will be placed into the {@link android.widget.ListView}. The +{@link android.widget.ArrayAdapter} constructor takes the application {@link +android.content.Context}, the +layout description for each list item (created in +the previous step), and a {@link java.util.List} of objects to insert in the {@link +android.widget.ListView} (defined next).
+ +The {@link android.widget.ListView#setTextFilterEnabled(boolean)} method turns on text filtering +for the {@link android.widget.ListView}, so that when the user begins typing, the list will be +filtered.
+ +The {@link android.widget.ListView#setOnItemClickListener(OnItemClickListener)} method defines +the on-click listener for each item. When an item in the {@link android.widget.ListView} is clicked, +the {@link android.widget.AdapterView.OnItemClickListener#onItemClick(AdapterView,View,int,long) +onItemClick()} method is called and a {@link android.widget.Toast} message is displayed, using the +text from the clicked item.
+ +Tip: You can use list item designs provided by the platform
+instead of defining your own layout file for the {@link android.widget.ListAdapter}. For example,
+try using android.R.layout.simple_list_item_1 instead of
+R.layout.list_item.
static final String[] COUNTRIES = new String[] {
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
@@ -76,12 +128,40 @@ public void onCreate(Bundle savedInstanceState) {
"Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
};
+ This is the array of strings that will be placed into the {@link android.widget.ListView}.
You can scroll the list, or type to filter it. You should see something like this:
+You can scroll the list, or type to filter it, then click an item to see a message. You +should see something like this:
+Note that using a hard-coded string array is not the best design practice. One is +used in this tutorial for simplicity, in order to demonstrate the {@link +android.widget.ListView} widget. The better practice is to reference a string array +defined by an external resource, such as with a {@code <string-array>} +resource in your project {@code res/values/strings.xml} file. For example:
++<?xml version="1.0" encoding="utf-8"?> +<resources> + <string-array name="countries_array"> + <item>Bahrain</item> + <item>Bangladesh</item> + <item>Barbados</item> + <item>Belarus</item> + <item>Belgium</item> + <item>Belize</item> + <item>Benin</item> + </string-array> +</resources> ++
To use these resource strings for the {@link android.widget.ArrayAdapter}, replace the original +{@link android.app.ListActivity#setListAdapter(ListAdapter)} line with the following:
++String[] countries = getResources().getStringArray(R.array.countries_array); +setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, countries)); ++
Using the Google Maps library, you can create your own map-viewing Activity. In this +tutorial, you'll create a simple map application in two parts. In Part 1, you'll create an app that +shows a map the user can pan and zoom. In Part 2, you'll add overlay items that mark +points of interest.
+This tutorial requires that you have the Google Maps external library -installed in your SDK environment. By default the Android SDK includes the -Google APIs add-on, which in turn includes the Maps external library. If you -don't have the Google APIs SDK add-on, you can download it from this -location:
- -http://code.google.com/android/add-ons/google-apis
- -The Google APIs add-on requires Android 1.5 SDK or later release. After -installing the add-on in your SDK, set your project properties to use the build -target called "Google APIs Add-on". See the instructions for setting a build +
This tutorial requires that you have the external Google Maps library +installed in your SDK environment. The Maps library is included with the Google APIs +add-on, which you can install using the Android SDK and +AVD Manager. To learn how, see Adding SDK +Components.
+ +After installing the Google APIs add-on in your SDK, set your project properties to use the build +target called "Google APIs by Google Inc.". See the instructions for setting a build target in Developing in Eclipse with ADT or Developing in Other IDEs, as appropriate for your environment.
-You will also need to use the android tool to set up an AVD that uses the -Google APIs deployment target. See You will also need to set up a new AVD that uses the same Google APIs deployment target. See Android Virtual Devices for -more information. Once you have set up your environment, you will be able to -build and run the project described in this tutorial
+more information. + +For reference material, see the Google Maps +library documentation.
A MapView allows you to create your own map-viewing Activity. -First, we'll create a simple Activity that can view and navigate a map. Then we will add some overlay items.
+<application> element:
-
- <uses-library android:name="com.google.android.maps" />-
<manifest> element:
- <uses-permission android:name="android.permission.INTERNET" />-
AndroidManifest.xml
+ file and add the following as a child of the <application> element:
+ <uses-library android:name="com.google.android.maps" />+
<manifest> element:
+ <uses-permission android:name="android.permission.INTERNET" />+
+<activity android:name=".HelloGoogleMaps" android:label="@string/app_name" + android:theme="@android:style/Theme.NoTitleBar"> ++
res/layout/main.xml file and add a single
+ {@code com.google.android.maps.MapView} as the root node:
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/mainlayout"
- android:orientation="vertical"
+<com.google.android.maps.MapView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/mapview"
android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
-
- <com.google.android.maps.MapView
- android:id="@+id/mapview"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:clickable="true"
- android:apiKey="Your Maps API Key"
- />
-
-</RelativeLayout>
+ android:layout_height="fill_parent"
+ android:clickable="true"
+ android:apiKey="Your Maps API Key goes here"
+/>
- The clickable attribute defines whether you want to allow user-interaction with the map.
- In this case, we set it "true" so that the user can navigate.
The apiKey attribute holds the Google Maps API Key that proves your application and signer
- certificate has been registered with the Google Maps service. Because MapView uses Google Maps data, this key is required
- in order to receive the map data, even while you are developing. Registration is free and it only takes a couple
- minutes to register your certificate and receive a Maps API Key. For instructions on getting a key, read
- Obtaining a Maps API Key.
- (For the purpose of this tutorial, you should register with the fingerprint of the SDK debug certificate.)
- Once you've acquired the Maps API Key, insert it for the apiKey value.
public class HelloMapView extends MapActivity {
-
- isRouteDisplayed() method is required, so add it inside the class:
+ The android:clickable attribute defines whether you want to allow
+ user-interaction with the map. If this is "false" then touching the map does nothing.
The android:apiKey attribute holds the Maps API Key for your
+ application, which proves your application and signer certificate has been registered with the
+ Maps service. This is required in order to receive the map data, even while you are
+ developing. Registration to the service is free and it only takes a couple
+ minutes to register your certificate and get a Maps API Key.
Go now to get a key. For instructions, read
+ Obtaining a Maps API
+ Key. For the purpose of this tutorial, you should register
+ with the SDK debug certificate, which will only be valid while your application is signed
+ with the debug key (once you sign with your private key, you will need a new API key).
+ When you get your key, insert it for the value of android:apiKey.
HelloGoogleMaps.java file. For this Activity, extend
+ {@code MapActivity} (instead of {@code android.app.Activity}):
+
+ public class HelloGoogleMaps extends MapActivity {
+ This is a special sub-class of {@link android.app.Activity}, provided by the Maps + library, which provides important map capabilities.
+ +isRouteDisplayed() method is required, so
+ override this method:
@Override
protected boolean isRouteDisplayed() {
return false;
}
-You can actually run this now, but all it does is allow you to pan around the map.
-Android provides a handy {@link android.widget.ZoomControls} widget for zooming in and out of a View.
-MapView can automatically hook one for us by requesting it with the getZoomControls()
-method. Let's do this.
This method is required for some accounting from the Maps service to see if you're currently +displaying any route information. In this case, you're not, so return false.
+-<LinearLayout - android:id="@+id/zoomview" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignBottom="@id/mapview" - android:layout_centerHorizontal="true" -/>- -
It doesn't really matter what kind of ViewGroup we use, because we just want a - container that we can position within our root RelativeLayout.
- -The last two attributes are available only to an element that's a child of a
- RelativeLayout. layout_alignBottom aligns the bottom of this element to the bottom of
- the element identified with a resource tag (which must be a sibling to this element).
- layout_centerHorizontal centers this on the horizontal plane.
-LinearLayout linearLayout; -MapView mapView; -ZoomControls mZoom;
onCreate(). We'll capture the LinearLayout and
- MapView through their layout resources. Then get the ZoomControls from the MapView::
+@Override
+public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+}
+
+This loads the layout file created above. In fact, this is now a workable application that will +display map tiles and allow the user to pan around the map. But there's no ability to zoom. +Fortunately, there's a very simple zoom feature built into the {@code MapView} class, which you can +summon with {@code setBuiltInZoomControls(boolean)}. Do this at the end of the {@link +android.app.Activity#onCreate(Bundle) onCreate()} method:
-linearLayout = (LinearLayout) findViewById(R.id.zoomview); -mapView = (MapView) findViewById(R.id.mapview); -mZoom = (ZoomControls) mapView.getZoomControls();- -
By using the ZoomControls object provided by MapView, we don't have to do any of the work - required to actually perform the zoom operations. The ZoomControls widget that MapView - returns for us is already hooked into the MapView and works as soon as we add it to the - layout. The controls will appear whenever the user touches the map, then dissapear after - a few moments of inactivity.
linearLayout.addView(mZoom);
So, we now have full interaction controls. All well and good, but what we really want our map -for is custom markers and layovers. Let's add some Overlay -objects to our map. To do this, we're going to -implement the ItemizedOverlay -class, which can manage a whole set of Overlay items for us.
+So, now you have a map, but in many cases you'll also want to create your own map +markers and lay-overs. That's what you'll do now. In order to do so, you must implement the +{@code ItemizedOverlay} class, which can manage a whole set of {@code Overlay} (which are the +individual items placed on the map).
When using Eclipse, right-click the package name in the Eclipse Package Explorer, and select New > Class. Fill-in - the Name field as HelloItemizedOverlay. For the Superclass, enter - com.google.android.maps.ItemizedOverlay. Click the checkbox for Constructors from - superclass. Click Finish.
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
super(boundCenterBottom(defaultMarker));
HelloItemizedOverlay that implements
+ {@code ItemizedOverlay}.
+
+ When using Eclipse, right-click the package name in the Eclipse Package Explorer, and + select New > Class. Fill-in + the Name field as HelloItemizedOverlay. For the Superclass, enter + "com.google.android.maps.ItemizedOverlay". Click the checkbox for Constructors from + superclass. Click Finish.
OverlayItem {@link java.util.ArrayList}, in which you'll put
+ each of the OverlayItem objects you want on the map. Add this at the top of the
+ HelloItemizedOverlay class:
+
+ private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();+
HelloItemizedOverlay constructors. The constructor must
+ define the default marker for each of the {@code OverlayItem}s. In order for the {@link
+ android.graphics.drawable.Drawable} to actually get drawn, it must have its bounds defined. Most
+ commonly, you want the center-point at the bottom of the image to be the point at which it's
+ attached to the map coordinates. This is handled for you with the {@code boundCenterBottom()}
+ method. Wrap this around our defaultMarker, so the super constructor call looks like this:
+
+public HelloItemizedOverlay(Drawable defaultMarker) {
+ super(boundCenterBottom(defaultMarker));
+}
+
+
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}
+ Each time you add a new {@code OverlayItem} to the ArrayList, you must call
+ populate() for the {@code ItemizedOverlay}, which will read each of the
+ {@code OverlayItem}s and prepare them to be drawn.
Each time we add a new OverlayItem, we must call populate(), which will read each of out
- OverlayItems and prepare them to be drawn.
populate() method to read each OverlayItem, it will make a request to
- createItem(int). We must define this method to properly read from our ArrayList. Replace the
- existing contents of the createItem method with a get() call to our ArrayList:
+ populate() method executes, it will call createItem(int) in
+ the {@code ItemizedOverlay} to retrieve each {@code OverlayItem}. You must override this method to
+ properly read from the ArrayList and return the {@code OverlayItem} from the position specified
+ by the given integer. Your override method should look like this:
@Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
-size() method. Replace the existing contents of the
- method with a size request to our ArrayList:
+
+ return mOverlays.size();-
size() method to return the current number of
+ items in the ArrayList:
+
+@Override
+public int size() {
+ return mOverlays.size();
+}
+
+
+public HelloItemizedOverlay(Drawable defaultMarker, Context context) {
+ super(defaultMarker);
+ mContext = context;
+}
+
+ This passes the {@code defaultMarker} up to the default constructor to bound its coordinates + and then initialize {@code mContext} with the given {@link android.content.Context}.
-That's it for the HelloItemizedOverlay class. We're now ready to use it.
+Then override the {@code onTap(int)} callback method, which will handle the event + when an item is tapped by the user:
+
+@Override
+protected boolean onTap(int index) {
+ OverlayItem item = mOverlays.get(index);
+ AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
+ dialog.setTitle(item.getTitle());
+ dialog.setMessage(item.getSnippet())
+ dialog.show();
+ return true;
+}
+
+ This uses the member {@code android.content.Context} to create a new {@link +android.app.AlertDialog.Builder} and uses the tapped {@code OverlayItem}'s title and snippet for +the dialog's title and message text. (You'll see the {@code OverlayItem} title and snippet defined +when you create it below.)
+Go back to the HelloMapView -class. We'll start by creating one OverlayItem, adding to an instance of our HelloItemizedOverlay, -and then adding this to the MapView.
+ -
-First, we need the image that we'll use for our map overlay. Here, we'll use the Android on the -right as our marker. Drag this image (or your own) to the res/drawable/ directory of your project workspace.
+You're now done with the HelloItemizedOverlay class and can start using it
+to add items on the map.
Now we're ready to work in the HelloMapView:
+Go back to the HelloGoogleMaps class. In the following procedure, you'll create an
+{@code OverlayItem} and add it to an instance of the HelloItemizedOverlay class, then
+add the HelloItemizedOverlay to the MapView using a {@code GeoPoint}
+to define its coordinates on the map.
-List<Overlay> mapOverlays; -Drawable drawable; -HelloItemizedOverlay itemizedOverlay;
res/drawable/ directory of your
+ project.onCreate() method. Instantiate the
- new fields:
+ -mapOverlays = mapView.getOverlays(); -drawable = this.getResources().getDrawable(R.drawable.androidmarker); -itemizedoverlay = new HelloItemizedOverlay(drawable);- -
All overlay elements on a map are held by the MapView, so when we want to add some, we must
- first retrieve the List with getOverlays() methods. We instantiate the Drawable, which will
- be used as our map marker, by using our Context resources to get the Drawable we placed in
- the res/drawable/ directory (androidmarker.png). Our HelloItemizedOverlay takes the Drawable in order to set the
- default marker.
All overlay elements on a map are held by the {@code MapView}, so when you want to add some,
+ you have to get a list from the getOverlays() method. Then instantiate the {@link
+ android.graphics.drawable.Drawable} used for the map marker, which was saved in the {@code
+ res/drawable/} directory. The constructor for {@code HelloItemizedOverlay} (your custom {@code
+ ItemizedOverlay}) takes the Drawable in order to set the default marker for all overlay
+ items.
GeoPoint point = new GeoPoint(19240000,-99120000); -OverlayItem overlayitem = new OverlayItem(point, "", "");- -
GeoPoint coordinates are based in microdegrees (degrees * 1e6). The OverlayItem takes this - GeoPoint and two strings. Here, we won't concern ourselves with the strings, which can display - text when we click our marker, because we haven't yet written the click handler for the OverlayItem.
{@code GeoPoint} coordinates are specified in microdegrees (degrees * 1e6). The
+ {@code OverlayItem} constructor accepts the {@code GeoPoint} location, a string for the
+ item's title, and a string for the item's snippet text, respectively.
itemizedoverlay.addOverlay(overlayitem); -mapOverlays.add(itemizedoverlay);
We've sent our droid to Mexico City. Hola, Mundo!
You should see the following:
+When you tap the overlay item, you'll see the dialog appear.
-Because we created our ItemizedOverlay class with an ArrayList, we can continue adding new
-OverlayItems. Try adding another one. Before the addOverlay() method is called, add these lines:
Because the {@code ItemizedOverlay} class uses an {@code java.util.ArrayList} for all of the
+{@code OverlayItem}s, it's easy to add more. Try adding another one. Before the
+addOverlay() method is called, add these lines:
GeoPoint point2 = new GeoPoint(35410000, 139460000); -OverlayItem overlayitem2 = new OverlayItem(point2, "", ""); +OverlayItem overlayitem2 = new OverlayItem(point2, "Sekai, konichiwa!", "I'm in Japan!");-
Run it again... We've sent a new droid to Tokyo. Sekai, konichiwa!
+Run the application again. (You probably need to move the map to find the new overlay item.)
diff --git a/docs/html/resources/tutorials/views/hello-relativelayout.jd b/docs/html/resources/tutorials/views/hello-relativelayout.jd index 1b91537..adc1179 100644 --- a/docs/html/resources/tutorials/views/hello-relativelayout.jd +++ b/docs/html/resources/tutorials/views/hello-relativelayout.jd @@ -1,33 +1,38 @@ -page.title=Hello, RelativeLayout +page.title=Relative Layout parent.title=Hello, Views parent.link=index.html @jd:body -A {@link android.widget.RelativeLayout} is a ViewGroup that allows you to layout child elements -in positions relative to the parent or siblings elements.
+{@link android.widget.RelativeLayout} is a {@link android.view.ViewGroup} that displays +child {@link android.view.View} elements in relative positions. The position of a {@link +android.view.View} can be specified as relative to sibling elements (such as to the left-of or below +a given element) or in positions relative to the {@link android.widget.RelativeLayout} area (such as +aligned to the bottom, left of center).
+ +A {@link android.widget.RelativeLayout} is a very powerful utility for designing a user +interface because it can eliminate nested {@link android.view.ViewGroup}s. If you find +yourself using several nested {@link android.widget.LinearLayout} groups, you may be able to +replace them with a single {@link android.widget.RelativeLayout}.
res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
-
<TextView
android:id="@+id/label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Type here:"/>
-
<EditText
android:id="@+id/entry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background"
android:layout_below="@id/label"/>
-
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
@@ -36,39 +41,48 @@ in positions relative to the parent or siblings elements.
android:layout_alignParentRight="true"
android:layout_marginLeft="10dip"
android:text="OK" />
-
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/ok"
android:layout_alignTop="@id/ok"
android:text="Cancel" />
-
</RelativeLayout>
-Pay attention to each of the additional layout_* attributes (besides the
-usual width and height, which are required for all elements). When using relative layout,
-we use attributes like layout_below and layout_toLeftOf to describe
-how we'd like to position each View. Naturally, these are different relative positions, and the
-value of the attribute is the id of the element we want the position relative to.
Notice each of the android:layout_* attributes, such as layout_below,
+layout_alignParentRight, and layout_toLeftOf. When using a {@link
+android.widget.RelativeLayout}, you can use these attributes to describe
+how you want to position each {@link android.view.View}. Each one of these attributes define a
+different kind
+of relative position. Some attributes use the resource ID of a sibling {@link android.view.View}
+to define its own relative position. For example, the last {@link android.widget.Button} is
+defined to lie to the left-of and aligned-with-the-top-of the {@link android.view.View}
+identified by the ID ok (which is the previous {@link android.widget.Button}).
All of the available layout attributes are defined in {@link +android.widget.RelativeLayout.LayoutParams}.
onCreate() method:
+
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
-R.layout.main refers to the main.xml layout file.
The {@link android.app.Activity#setContentView(int)} method loads the
+layout file for the {@link android.app.Activity}, specified by the resource
+ID — R.layout.main refers to the res/layout/main.xml layout
+file.
You should see the following:
+You should see the following layout:
A {@link android.widget.Spinner} is a widget that allows the user to select an item from a group. -It is similar to a dropdown list and will allow scrolling when the -list exceeds the available vertical space on the screen.
+{@link android.widget.Spinner} is a widget similar to a drop-down list for selecting items.
+In this tutorial, you'll create +a simple spinner widget that displays a list of planets. When one is selected, a toast message +will display the selected item.
res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -19,41 +19,34 @@ list exceeds the available vertical space on the screen.
android:padding="10dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
-
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
- android:text="Please select a planet:"
+ android:text="@string/planet_prompt"
/>
-
<Spinner
android:id="@+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:drawSelectorOnTop="true"
android:prompt="@string/planet_prompt"
/>
-
</LinearLayout>
- Notice that the Spinner's android:prompt is a string resource. In
- this case, Android does not allow it to be a string, it must be a reference to a resource.
- So...
<string>
-element inside the <resources> element:
--<string name="planet_prompt">Choose a planet</string> -+
Notice that the {@link android.widget.TextView}'s android:text attribute and the
+{@link android.widget.Spinner}'s android:prompt attribute both reference the same
+string resource. This text behaves as a title for the widget. When applied to the {@link
+android.widget.Spinner}, the title text will appear
+in the selection dialog that appears upon selecting the widget.
strings.xml file in res/values/ and edit the file to look
+like this:
+<?xml version="1.0" encoding="utf-8"?>
<resources>
-
- <string-array name="planets">
+ <string name="planet_prompt">Choose a planet</string>
+ <string-array name="planets_array">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
@@ -63,35 +56,85 @@ element inside the <resources> element:
<item>Uranus</item>
<item>Neptune</item>
</string-array>
-
</resources>
- This is the list of items (planets) that the user can select from in the Spinner widget.
+The {@code <string>} element defines the title string referenced by the {@link +android.widget.TextView} and {@link android.widget.Spinner} in the layout above. The {@code +<string-array} element defines the list of strings that will be displayed as the list in +the {@link android.widget.Spinner} widget.
HelloSpinner.java file and insert the following code for the {@link
+android.app.Activity#onCreate(Bundle) onCreate()} method:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
- Spinner s = (Spinner) findViewById(R.id.spinner);
- ArrayAdapter adapter = ArrayAdapter.createFromResource(
- this, R.array.planets, android.R.layout.simple_spinner_item);
+ Spinner spinner = (Spinner) findViewById(R.id.spinner);
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
+ this, R.array.planets_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- s.setAdapter(adapter);
+ spinner.setAdapter(adapter);
+}
+
+ After the {@code main.xml} layout is set as the content view, the {@link +android.widget.Spinner} widget is captured from the layout with {@link +android.app.Activity#findViewById(int)}. The {@link +android.widget.ArrayAdapter#createFromResource(Context,int,int) createFromResource()} method then +creates a new {@link android.widget.ArrayAdapter}, which binds each item in the string array +to the initial appearance for the {@link android.widget.Spinner} (which is how each item will +appear in the spinner when selected). The {@code +R.array.planets_array} ID references the {@code string-array} defined above and the +{@code android.R.layout.simple_spinner_item} ID references a layout for the standard spinner +appearance, defined by the platform. Then {@link +android.widget.ArrayAdapter#setDropDownViewResource(int)} is called to define the appearance for +each item when the widget is opened ({@code simple_spinner_dropdown_item} is +another standard layout defined by the platform). Finally, the {@link android.widget.ArrayAdapter} +is set to associate all of its items with the {@link android.widget.Spinner} by calling {@link +android.widget.AdapterView#setAdapter(T)}.
+
+public class MyOnItemSelectedListener implements OnItemSelectedListener {
+
+ public void onItemSelected(AdapterView<?> parent,
+ View view, int pos, long id) {
+ Toast.makeText(parent.getContext()), "The planet is " +
+ parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
+ }
+
+ public void onNothingSelected(AdapterView> parent) {
+ // Do nothing.
+ }
}
- That's it. We start by creating a Spinner from our layout. We then create an {@link android.widget.ArrayAdapter}
- that binds each element of our string array to a layout view—we pass createFromResource our Context,
- the array of selectable items and the type of layout we'd like each one bound to. We then call
- setDropDownViewResource() to define the type of layout in which to present the
- entire collection. Finally, we set this Adapter to associate with our Spinner,
- so the string items have a place to go.
The {@link android.widget.AdapterView.OnItemSelectedListener} requires the {@link +android.widget.AdapterView.OnItemSelectedListener#onItemSelected(AdapterView,View,int,long) +onItemSelected()} and {@link +android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(AdapterView) +onNothingSelected()} callback methods. The former is called when an item from the {@link +android.widget.AdapterView} is selected, in which case, a short {@link android.widget.Toast} +message displays the selected text; and the latter is called when a selection disappears from the +{@link android.widget.AdapterView}, which doesn't happen in this case, so it's ignored.
++ spinner.setOnItemSelectedListener(new MyOnItemSelectedListener()); ++
This creates a new anonymous instance of the {@code MyOnItemSelectedListener} and sets it as the +listener for the {@link android.widget.Spinner}.
It should look like this:
diff --git a/docs/html/resources/tutorials/views/hello-tablelayout.jd b/docs/html/resources/tutorials/views/hello-tablelayout.jd
index 83d6f5d..c8c5982 100644
--- a/docs/html/resources/tutorials/views/hello-tablelayout.jd
+++ b/docs/html/resources/tutorials/views/hello-tablelayout.jd
@@ -1,16 +1,15 @@
-page.title=Hello, TableLayout
+page.title=Table Layout
parent.title=Hello, Views
parent.link=index.html
@jd:body
-A {@link android.widget.TableLayout} is a ViewGroup that -will lay child View elements into rows and columns.
+{@link android.widget.TableLayout} is a {@link android.view.ViewGroup} that +displays child {@link android.view.View} elements in rows and columns.
res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -89,21 +88,28 @@ will lay child View elements into rows and columns.
</TableRow>
</TableLayout>
-Notice how this resembles the structure of an HTML table. TableLayout is like the
-table element; TableRow is like a tr element; but for our cells like
-the html td element, we can use any kind of View. Here, we use TextView for the cells.
Notice how this resembles the structure of an HTML table. The {@link android.widget.TableLayout}
+element is like the HTML <table> element; {@link android.widget.TableRow} is like
+a ><tr>> element;
+but for the cells, you can use any kind of {@link android.view.View} element. In this example, a
+{@link android.widget.TextView} is used for each cell. In between some of the rows, there is also a
+basic {@link android.view.View}, which is used to draw a horizontal line.
onCreate() method:
+
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
-R.layout.main refers to the main.xml layout file.
The {@link android.app.Activity#setContentView(int)} method loads the
+layout file for the {@link android.app.Activity}, specified by the resource
+ID — R.layout.main refers to the res/layout/main.xml layout
+file.
You should see the following:
diff --git a/docs/html/resources/tutorials/views/hello-tabwidget.jd b/docs/html/resources/tutorials/views/hello-tabwidget.jd
index 8424616..199ceef 100644
--- a/docs/html/resources/tutorials/views/hello-tabwidget.jd
+++ b/docs/html/resources/tutorials/views/hello-tabwidget.jd
@@ -1,14 +1,72 @@
-page.title=Hello, TabWidget
+page.title=Tab Layout
parent.title=Hello, Views
parent.link=index.html
@jd:body
-A {@link android.widget.TabWidget} offers the ability to easily draw an interface that uses -tabs to navigate between different views.
+To create a tabbed UI, you need to use a {@link android.widget.TabHost} and a {@link +android.widget.TabWidget}. The {@link android.widget.TabHost} must be the root node for the layout, +which contains both the {@link android.widget.TabWidget} for displaying the tabs and a {@link +android.widget.FrameLayout} for displaying the tab content.
+ +You can implement your tab content in one of two ways: use the tabs to swap +{@link android.view.View}s within the same {@link android.app.Activity}, or use the tabs to change +between entirely separate activities. Which method you want for your application will depend on your +demands, but if each tab provides a distinct user activity, then it probably makes sense to use +a separate {@link android.app.Activity} for each tab, so that you can better manage the application +in discrete groups, rather than one massive application and layout.
+ +In this tutorial, you'll create a tabbed UI that uses a separate {@link +android.app.Activity} for each tab.
ArtistsActivity, AlbumsActivity, and SongsActivity. These
+will each represent a separate tab. For now, make each one display a simple message using a {@link
+android.widget.TextView}. For example:
+
+public class ArtistsActivity extends Activity {
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ TextView textview = new TextView(this);
+ textview.setText("This is the Artists tab");
+ setContentView(textview);
+ }
+}
+
+ Notice that this doesn't use a layout file. Just create a {@link +android.widget.TextView}, give it some text and set that as the content. Duplicate this for +each of the three activities.
+ +
+
+
+
Copy these images for use in this tutorial. Save them into your project
+res/drawable/ directory. You now need to create a {@link
+android.graphics.drawable.Drawable} with XML that specifies which image
+to use for each state. Create a new file in res/drawable/ named
+ic_tab_artists.xml and insert the following:
+<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- When selected, use grey --> + <item android:drawable="@drawable/ic_tab_artists_grey" + android:state_selected="true" /> + <!-- When not selected, use white--> + <item android:drawable="@drawable/ic_tab_artists_white" /> +</selector> ++
This is an XML definition for a {@link android.graphics.drawable.Drawable}, which you will +reference as the image for a tab. When the image state changes, the image will automatically +switch between the images defined here.
+ +res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
@@ -18,7 +76,8 @@ tabs to navigate between different views.
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
- android:layout_height="fill_parent">
+ android:layout_height="fill_parent"
+ android:padding="5dp">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
@@ -26,94 +85,111 @@ tabs to navigate between different views.
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <TextView
- android:id="@+id/textview1"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:text="this is a tab" />
- <TextView
- android:id="@+id/textview2"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:text="this is another tab" />
- <TextView
- android:id="@+id/textview3"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:text="this is a third tab" />
- </FrameLayout>
+ android:layout_height="fill_parent"
+ android;padding="5dp" />
</LinearLayout>
</TabHost>
- Here, we've created a {@link android.widget.TabHost} that contains the entire layout of the Activity. - A TabHost requires two descendant elements: a {@link android.widget.TabWidget} and a {@link android.widget.FrameLayout}. - In order to properly layout these elements, we've put them inside a vertical {@link android.widget.LinearLayout}. - The FrameLayout is where we keep the content that will change with each tab. Each child in the FrameLayout will - be associated with a different tab. - In this case, each tab simply shows a different {@link android.widget.TextView} with some text.
-Notice that the TabWidget and the FrameLayout elements have specific android namespace IDs. These are necessary
- so that the TabHost can automatically retireve references to them, populate the TabWidget with the tabs that we'll define
- in our code, and swap the views in the FrameLayout. We've also defined our own IDs for each TextView, which we'll use to
- associate each tab with the view that it should reveal.
Of course, you can - make these child views as large as complex as you'd like — instead of the TextView elements, - you could start with other layout views and build a unique layout hierarchy for each tab.
+This is the layout that will display the tabs and provide navigation between each {@link + android.app.Activity} created above.
+The {@link android.widget.TabHost} requires that a {@link android.widget.TabWidget} and a +{@link android.widget.FrameLayout} both live somewhere within it. To position the {@link +android.widget.TabWidget} and {@link android.widget.FrameLayout} vertically, a {@link +android.widget.LinearLayout} is used. The {@link android.widget.FrameLayout} is where the content +for each tab goes, which is empty now because the {@link android.widget.TabHost} will automatically +embed each {@link android.app.Activity} within it.
+Notice that the {@link android.widget.TabWidget} and the {@link android.widget.FrameLayout} + elements have the IDs {@code tabs} and {@code tabcontent}, respectively. These names + must be used so that the {@link android.widget.TabHost} can retrieve references to each of + them. It expects exactly these names.
TabActivity.
- By default, Eclipse creates a class that extends Activity. Change it to
- extend TabActivity:
+ +
HelloTabWidget.java and make it extend {@link
+ android.app.TabActivity}:
+
public class HelloTabWidget extends TabActivity {
-
+
onCreate method like this:
- +
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
- mTabHost = getTabHost();
-
- mTabHost.addTab(mTabHost.newTabSpec("tab_test1").setIndicator("TAB 1").setContent(R.id.textview1));
- mTabHost.addTab(mTabHost.newTabSpec("tab_test2").setIndicator("TAB 2").setContent(R.id.textview2));
- mTabHost.addTab(mTabHost.newTabSpec("tab_test3").setIndicator("TAB 3").setContent(R.id.textview3));
-
- mTabHost.setCurrentTab(0);
+ Resources res = getResources(); // Resource object to get Drawables
+ TabHost tabHost = getTabHost(); // The activity TabHost
+ TabHost.TabSpec spec; // Resusable TabSpec for each tab
+ Intent intent; // Reusable Intent for each tab
+
+ // Create an Intent to launch an Activity for the tab (to be reused)
+ intent = new Intent().setClass(this, ArtistsActivity.class);
+
+ // Initialize a TabSpec for each tab and add it to the TabHost
+ spec = tabHost.newTabSpec("artists").setIndicator("Artists",
+ res.getDrawable(R.drawable.ic_tab_artists))
+ .setContent(intent);
+ tabHost.addTab(spec);
+
+ // Do the same for the other tabs
+ intent = new Intent().setClass(this, AlbumsActivity.class);
+ spec = tabHost.newTabSpec("albums").setIndicator("Albums",
+ res.getDrawable(R.drawable.ic_tab_albums))
+ .setContent(intent);
+ mTabHost.addTab(spec);
+
+ intent = new Intent().setClass(this, SongsActivity.class);
+ spec = tabHost.newTabSpec("songs").setIndicator("Songs",
+ res.getDrawable(R.drawable.ic_tab_songs))
+ .setContent(intent);
+ tabHost.addTab(spec);
+
+ tabHost.setCurrentTab(getIntent());
}
- As usual, we start by setting our layout.
-We then call the TabActivity method getTabHost(),
- which returns us a reference to the TabHost we created in our layout. Upon our TabHost, we call addTab()
- for each of the tabs that we want to add to the TabWidget. Each time we call this, we pass a
- {@link android.widget.TabHost.TabSpec} that we build on the fly, and with it, chain together two necessary methods:
- setIndicator() to set the text for the tab button, and setContent() to define
- which View we want to associate with the tab and reveal when pressed. Our indicator is just a text string and
- our content is an ID reference to the TextView elements we inserted in the FrameLayout.
At the end, we call setCurrentTab() to define which tab should be opened by default. The tabs
- are saved like a zero-based array, so to open the first tab, we pass zero (0).
This sets up each tab with their text and icon, and assigns each one an {@link +android.app.Activity}.
+A reference to the {@link android.widget.TabHost} is first captured with {@link +android.app.TabActivity#getTabHost()}. Then, for +each tab, a {@link android.widget.TabHost.TabSpec} is created to define the tab properties. The +{@link android.widget.TabHost#newTabSpec(String)} method creates a new {@link +android.widget.TabHost.TabSpec} identified by the given string tag. For each +{@link android.widget.TabHost.TabSpec}, {@link +android.widget.TabHost.TabSpec#setIndicator(CharSequence,Drawable)} is called to set the text and +icon for the tab, and {@link android.widget.TabHost.TabSpec#setContent(Intent)} is called to specify +the {@link android.content.Intent} to opens the appropriate {@link android.app.Activity}. Each +{@link android.widget.TabHost.TabSpec} is then added to the {@link android.widget.TabHost} by +calling {@link android.widget.TabHost#addTab(TabHost.TabSpec)}.
+ +At the very end, {@link + android.widget.TabHost#setCurrentTab(int)} opens the tab to be displayed by default, specified + by the index position of the tab.
+ +Notice that not once was the {@link android.widget.TabWidget} object referenced. This is + because a {@link android.widget.TabWidget} must always be a child of a {@link + android.widget.TabHost}, which is what you use for almost all interaction with the tabs. So when + a tab is added to the {@link android.widget.TabHost}, it's automatically added to the child + {@link android.widget.TabWidget}.
<application> tag. It should end up like this:
- -<application android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar"> + +
NoTitleBar theme to the
+HelloTabWidget's
+ <activity> tag. This will remove the default application title from the top
+ of the layout, leaving more space for the tabs, which effectively operate as their own titles.
+ The <activity> tag should look like this:
++<activity android:name=".HelloTabWidget" android:label="@string/app_name" + android:theme="@android:style/Theme.NoTitleBar">
Your application should look like this:
-You can include icons in your tabs by passing a
-{@link android.graphics.drawable.Drawable} when you call setIndicator(). Here's an example
-that uses a Drawable created from an image in the project resources:
setIndicator("TAB 1", getResources().getDrawable(R.drawable.tab_icon))
-A {@link android.widget.TimePicker} is a widget that allows the -user to select the time by hour, minute and AM or PM.
+To provide a widget for selecting a time, use the {@link android.widget.TimePicker} +widget, which allows the user to select the hour and minute in a familiar interface.
+In this tutorial, you'll create a {@link android.app.TimePickerDialog}, which presents the +time picker in a floating dialog box at the press of a button. When the time is set by +the user, a {@link android.widget.TextView} will update with the new date.
res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
-
<TextView android:id="@+id/timeDisplay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""/>
-
<Button android:id="@+id/pickTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change the time"/>
-
</LinearLayout>
- For the layout, we're using a vertical LinearLayout, with a {@link android.widget.TextView} that - will display the time and a {@link android.widget.Button} that will initiate the - {@link android.widget.TimePicker} dialog. - With this layout, the TextView will sit above the Button. - The text value in the TextView is set empty, as it will be filled by our Activity - with the current time.
--private TextView mTimeDisplay; -private Button mPickTime; - -private int mHour; -private int mMinute; - -static final int TIME_DIALOG_ID = 0; +This is a basic {@link android.widget.LinearLayout} with a {@link android.widget.TextView} +that will display the time and a {@link android.widget.Button} that will open the {@link +android.app.TimePickerDialog}.
+
HelloTimePicker.java and insert the following class members:
++ private TextView mTimeDisplay; + private Button mPickTime; - // get the current time - final Calendar c = Calendar.getInstance(); - mHour = c.get(Calendar.HOUR_OF_DAY); - mMinute = c.get(Calendar.MINUTE); + private int mHour; + private int mMinute; - // display the current date - updateDisplay(); -} + static final int TIME_DIALOG_ID = 0;-
Tip: Press Ctrl(or Cmd) + Shift + O to import all needed packages.
-We start by instantiating variables for our View elements and time fields.
- The TIME_DIALOG_ID is a static integer that uniquely identifies the dialog. In the
- onCreate() method, we get prepared by setting the layout and capturing the View elements.
- We then set an on-click listener for the Button, so that when it is clicked, it will
- show our TimePicker dialog. The showDialog() method will perform a callback
- to our Activity. (We'll define this callback in the next section.) We then create an
- instance of {@link java.util.Calendar} and get the current hour and minute. Finally, we call
- updateDisplay()—our own method that will fill the TextView with the time.
onCreate() method, add the onCreateDialog() callback method:
+This declares variables for the layout elements and time fields.
+The TIME_DIALOG_ID is a static integer that uniquely identifies the dialog.
-@Override
-protected Dialog onCreateDialog(int id) {
- switch (id) {
- case TIME_DIALOG_ID:
- return new TimePickerDialog(this,
- mTimeSetListener, mHour, mMinute, false);
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ // capture our View elements
+ mTimeDisplay = (TextView) findViewById(R.id.timeDisplay);
+ mPickTime = (Button) findViewById(R.id.pickTime);
+
+ // add a click listener to the button
+ mPickTime.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ showDialog(TIME_DIALOG_ID);
+ }
+ });
+
+ // get the current time
+ final Calendar c = Calendar.getInstance();
+ mHour = c.get(Calendar.HOUR_OF_DAY);
+ mMinute = c.get(Calendar.MINUTE);
+
+ // display the current date
+ updateDisplay();
}
- return null;
-}
- This is passed the identifier we gave showDialog() and initializes
- the TimePicker to the time we retrieved from our Calendar instance. It will be called by
- showDialog().
First, the content is set to the main.xml layout and then the {@link
+android.widget.TextView} and {@link android.widget.Button} are captured with {@link
+android.app.Activity#findViewById(int)}.
+Then an {@link android.view.View.OnClickListener} is created for the {@link android.widget.Button},
+so that when clicked, it will call {@link
+android.app.Activity#showDialog(int)}, passing the unique integer ID for the time picker
+dialog. Using {@link android.app.Activity#showDialog(int)} allows the {@link
+android.app.Activity} to manage the life-cycle of the dialog and will call the {@link
+android.app.Activity#onCreateDialog(int)} callback method to request the {@link android.app.Dialog}
+that should be displayed (which you'll define later). After the on-click listener is set, a new
+{@link java.util.Calendar} is created to get the current hour and minute. Finally, the
+private updateDisplay() method is called in order to fill the {@link
+android.widget.TextView} with the current time.
updateDisplay() method:
+updateDisplay() and pad() methods:
// updates the time we display in the TextView
private void updateDisplay() {
@@ -109,13 +100,22 @@ private void updateDisplay() {
.append(pad(mHour)).append(":")
.append(pad(mMinute)));
}
+
+private static String pad(int c) {
+ if (c >= 10)
+ return String.valueOf(c);
+ else
+ return "0" + String.valueOf(c);
+}
- This simply takes our member fields for the time and inserts them in
- the mTimeDisplay TextView. Note that we call a new method, pad(),
- on the hour and minute. (We'll create this method in the last step.)
The updateDisplay() method uses the member fields for the time and inserts them in
+the mTimeDisplay {@link android.widget.TextView}. The pad() method returns
+the appropriate string representation of the hour or minute—it will prefix a zero to the
+number if it's a single digit.
// the callback received when the user "sets" the time in the dialog
private TimePickerDialog.OnTimeSetListener mTimeSetListener =
@@ -127,24 +127,31 @@ private TimePickerDialog.OnTimeSetListener mTimeSetListener =
}
};
- Now when the user is done setting the time (clicks the "Set" button), we update our member fields with - the new time and update our TextView.
+When the user is done setting the time (clicks the "Set" button), the
+onTimeSet() method is called and it updates the member fields with
+the new time and updates the layout's {@link android.widget.TextView}.
pad() method that we called from the updateDisplay():
+
+
-private static String pad(int c) {
- if (c >= 10)
- return String.valueOf(c);
- else
- return "0" + String.valueOf(c);
+@Override
+protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case TIME_DIALOG_ID:
+ return new TimePickerDialog(this,
+ mTimeSetListener, mHour, mMinute, false);
+ }
+ return null;
}
- This method returns the appropriate String representation of the hour or minute. - It will prefix a zero to the number if it's a single digit. -
+This is an {@link android.app.Activity} callback that is passed the identifier you passed to
+{@link android.app.Activity#showDialog(int)}, in the {@link android.widget.Button}'s on-click
+listener. When the ID matches, this initializes the {@link android.app.TimePickerDialog} with the
+member variables initialized at the end of onCreate() and the {@link
+android.app.TimePickerDialog.OnTimeSetListener} created in the previous step.
When you press the "Change the time" button, you should see the following:
@@ -152,6 +159,7 @@ private static String pad(int c) {
A {@link android.webkit.WebView} allows you to create your own web browser Activity. In this tutorial, -we'll create a simple Activity that can view web pages.
+{@link android.webkit.WebView} allows you to create your own window for viewing web pages (or even +develop a complete browser). In this tutorial, you'll create a simple {@link android.app.Activity} +that can view and navigate web pages.
res/layout/main.xml file and insert the following:
<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <WebView - android:id="@+id/webview" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - /> - -</LinearLayout> -
WebView webview;-
Then add the following at the end of the onCreate() method:
HelloWebView.java file.
+ At the top of the class, declare a {@link android.webkit.WebView} object:
+WebView mWebView;+
Then use the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} + method:
-webview = (WebView) findViewById(R.id.webview);
-webview.getSettings().setJavaScriptEnabled(true);
-webview.loadUrl("http://www.google.com");
+public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ mWebView = (WebView) findViewById(R.id.webview);
+ mWebView.getSettings().setJavaScriptEnabled(true);
+ mWebView.loadUrl("http://www.google.com");
+}
-
- This captures the WebView we created in our layout, then requests a - {@link android.webkit.WebSettings} object and enables JavaScript. - Then we load a URL.
<manifest> element:
-
- <uses-permission android:name="android.permission.INTERNET" />
You now have the world's simplest web page viewer. - It's not quite a browser yet. It only loads the page we've requested.
- -We can load a page, but as soon as we click a link, the default Android web browser -handles the Intent, instead of our own WebView handling the action. So now we'll -override the {@link android.webkit.WebViewClient} to enable us to handle our own URL loading.
- -This initializes the member {@link android.webkit.WebView} with the one from the + {@link android.app.Activity} layout; requests a {@link android.webkit.WebSettings} object with + {@link android.webkit.WebView#getSettings()}; and enables JavaScript for the {@link + android.webkit.WebView} with {@link android.webkit.WebSettings#setJavaScriptEnabled(boolean)}. + Finally, an initial web page is loaded with {@link + android.webkit.WebView#loadUrl(String)}.
+AndroidManifest.xml file
+ and add the following as a child of the <manifest> element:
+
+ <uses-permission android:name="android.permission.INTERNET" />
+<activity android:name=".HelloGoogleMaps" android:label="@string/app_name" + android:theme="@android:style/Theme.NoTitleBar"> ++
You now have a simplest web page viewer. + It's not quite a browser yet because as soon as you click a link, the default Android Browser + handles the Intent to view a web page, because this {@link android.app.Activity} isn't + technically enabled to do so. Instead of adding an intent filter to view web pages, you can + override the {@link android.webkit.WebViewClient} class and enable this {@link + android.app.Activity} to handle its own URL requests.
+HelloAndroid Activity, add this nested class:
private class HelloWebViewClient extends WebViewClient {
@Override
@@ -65,42 +74,51 @@ private class HelloWebViewClient extends WebViewClient {
view.loadUrl(url);
return true;
}
-}onCreate() method, set an instance of the HelloWebViewClient
- as our WebViewClient:
- webview.setWebViewClient(new WebViewClientDemo());- -
This line should immediately follow the initialization of our WebView object.
-What we've done is create a WebViewClient that will load any URL selected in our
-WebView in the same WebView. You can see this in the shouldOverrideUrlLoading()
-method, above—it is passed the current WebView and the URL, so all we do
-is load the URL in the given view. Returning true says that we've handled the URL
-ourselves and the event should not bubble-up.
If you try it again, new pages will now load in the HelloWebView Activity. However, you'll notice that -we can't navigate back. We need to handle the back button -on the device, so that it will return to the previous page, rather than exit the application.
+} + +HelloWebViewClient as the {@link android.webkit.WebViewClient}:
+ mWebView.setWebViewClient(new WebViewClientDemo());+ +
This line can go anywhere following the initialization of the {@link + android.webkit.WebView} object.
+This creates a {@link android.webkit.WebViewClient} that will load any URL selected from this
+ {@link android.webkit.WebView} into the same {@link android.webkit.WebView}. The
+ {@link android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String)} method is passed
+the current {@link android.webkit.WebView} and the URL requested, so all it needs to do is load
+the URL in the given view. Returning true says that the method has handled the URL
+and the event should not propagate (in which case, an Intent would be created that's handled by
+the Browser application).
If you run the application again, new pages will now load in this Activity. + However, you can't navigate back to previous pages. To do this, you need to handle the BACK + button on the device, so that it will return to the previous page, rather than exit the + application.
HelloWebView Activity:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {
- webview.goBack();
+ if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
+ mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
-}
- The condition uses a {@link android.view.KeyEvent} to check
- whether the key pressed is the BACK button and whether the
- WebView is actually capable of navigating back (if it has a history). If both are
- not true, then we send the event up the chain (and the Activity will close).
- But if both are true, then we call goBack(),
- which will navigate back one step in the history. We then return true to indicate
- that we've handled the event.
This {@link android.app.Activity#onKeyDown(int,KeyEvent)} callback method will be called
+ anytime a button is pressed while in the Activity. The condition inside uses the {@link
+ android.view.KeyEvent} to check whether the key pressed is the BACK button and whether the
+ {@link android.webkit.WebView} is actually capable of navigating back (if it has a history). If
+ both are true, then the {@link android.webkit.WebView#goBack()} method is called,
+ which will navigate back one step in the {@link android.webkit.WebView}
+ history.Returning true indicates that the event has been handled. If this condition
+ is not met, then the event is sent back to the system.
When you open the application, it should look like this:
@@ -111,8 +129,3 @@ public boolean onKeyDown(int keyCode, KeyEvent event) {
This collection of "Hello World"-style tutorials is designed -to get you quickly started with common Android Views and widgets. The aim is to let you copy and paste -these kinds of boring bits so you can focus on developing the code that makes your Android application rock. -Of course, we'll discuss some of the given code so that it all makes sense.
+This is a collection of "Hello World"-style tutorials designed +to get you started quickly with common Android layouts and widgets.
-Note that a certain amount of knowledge is assumed for these tutorials. If you haven't -completed the Hello, World tutorial, -please do so—it will teach you many things you should know about basic -Android development and Eclipse features. More specifically, you should know:
+A certain amount of knowledge is assumed for these tutorials. Before you start, +you should have completed the Hello, +World tutorial—it will teach you several things about basic +Android development. More specifically, you should know:
Please, also notice that, in order to make these tutorials simple, some may -not convey the better Android coding practices. In particular, many of them -use hard-coded strings in the layout files—the better practice is to reference strings from -your strings.xml file.
-With this knowledge, you're ready to begin, so take your pick.
-Note: In order to make these tutorials as simple as possible,
+some code may not conform to best practices for coding Android applications. In particular,
+hard-coded strings are used in places, when the better practice is to reference strings from a
+res/values/strings.xml resource file.
Tip: After you have pasted sample code into an Eclipse project, +press Ctrl (or Cmd) + Shift + O to import the required packages.
+ ++ +
-There are plenty more Views and widgets available. See the {@link android.view.View} class
+There are plenty more layouts and widgets available. See the {@link android.view.View} class
for more on View layouts, and the {@link android.widget widget package}
for more useful widgets. And for more raw code samples, visit the
-Api Demos.
-These can also be found offline, in /<sdk>/samples/ApiDemos.