diff options
author | Scott Main <smain@google.com> | 2010-01-19 19:59:24 -0800 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-01-19 19:59:24 -0800 |
commit | 382f924c951ff49e9bbb48a744a45fce1ad7ccd4 (patch) | |
tree | f3d8ba1e322a02572eba0b9edfce8bdaf5791838 /docs/html | |
parent | 97b108532f04f72af035e372be7b827f77888650 (diff) | |
parent | 5615ca1979caa79041bf16a2cae49f9cfadd7ee5 (diff) | |
download | frameworks_base-382f924c951ff49e9bbb48a744a45fce1ad7ccd4.zip frameworks_base-382f924c951ff49e9bbb48a744a45fce1ad7ccd4.tar.gz frameworks_base-382f924c951ff49e9bbb48a744a45fce1ad7ccd4.tar.bz2 |
am 5615ca19: docs: a lot of revision and expansion of the hello view tutorials includes new screenshots for some tutorials and a new sample images zip file
Merge commit '5615ca1979caa79041bf16a2cae49f9cfadd7ee5' into eclair-plus-aosp
* commit '5615ca1979caa79041bf16a2cae49f9cfadd7ee5':
docs: a lot of revision and expansion of the hello view tutorials
Diffstat (limited to 'docs/html')
27 files changed, 1537 insertions, 973 deletions
diff --git a/docs/html/resources/tutorials/views/hello-autocomplete.jd b/docs/html/resources/tutorials/views/hello-autocomplete.jd index fba1ad8..e26683d 100644 --- a/docs/html/resources/tutorials/views/hello-autocomplete.jd +++ b/docs/html/resources/tutorials/views/hello-autocomplete.jd @@ -1,56 +1,82 @@ -page.title=Hello, AutoCompleteTextView +page.title=Auto Complete parent.title=Hello, Views parent.link=index.html @jd:body -<p>{@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.</p> +<p>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}.</p> + +<p>In this tutorial, you will create a {@link android.widget.AutoCompleteTextView} widget that +provides suggestions for a country name.</p> <ol> - <li>Start a new project/Activity called HelloAutoComplete.</li> - <li>Open the layout file. - Make it like so: + <li>Start a new project named <em>HelloAutoComplete</em>.</li> + <li>Create an XML file named <code>list_item.xml</code> and save it inside the +<code>res/layout/</code> folder. Edit the file to look like this: +<pre> +<?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> +</pre> + <p>This file defines a simple {@link android.widget.TextView} that will be used for each +item that appears in the list of suggestions.</p> + </li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?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> </pre> + <p>The {@link android.widget.TextView} is a label that introduces the {@link +android.widget.AutoCompleteTextView} widget. </li> -<li>Open HelloAutoComplete.java and insert the following as the <code>onCreate</code> method: +<li>Open <code>HelloAutoComplete.java</code> and insert the following code for the {@link +android.app.Activity#onCreate(Bundle) onCreate()} method: <pre> @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); - AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit); - ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, - android.R.layout.simple_dropdown_item_1line, COUNTRIES); + AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.autocomplete_country); + ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, COUNTRIES); textView.setAdapter(adapter); } </pre> - <p>Here, we create an AutoComplteteTextView from our layout. We then - create an {@link android.widget.ArrayAdapter} that binds a <code>simple_dropdown_item_1line</code> - layout item to each entry in the <code>COUNTRIES</code> array (which we'll add next). - The last part sets the ArrayAdapter to associate with our AutoCompleteTextView.</p> + +<p>After the content view is set to the <code>main.xml</code> 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 <code>list_item.xml</code> layout +to each list item in the <code>COUNTRIES</code> 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.</p> </li> -<li>After the <code>onCreate()</code> method, add the String array: +<li>Inside the <code>HelloAutoComplete</code> class, add the string array: <pre> 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" }; </pre> - <p>This is the list of suggestions that will be offered as the user types into the - AutoCompleteTextView.</p> +<p>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.</p> </li> -<li>Now run it.</li> +<li>Run the application.</li> </ol> <p>As you type, you should see something like this:</p> <img src="images/hello-autocomplete.png" width="150px" /> +<h2>More Information</h2> + +<p>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:</p> +<pre> +<?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> +</pre> +<p>To use these resource strings for the {@link android.widget.ArrayAdapter}, replace the original +{@link android.widget.ArrayAdapter} constructor line with the following:</p> +<pre> +String[] countries = getResources().getStringArray(R.array.countries_array); +ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, countries); +</pre> + + <h3>References</h3> <ul> - <li>{@link android.R.layout}</li> <li>{@link android.widget.ArrayAdapter}</li> <li>{@link android.widget.AutoCompleteTextView}</li> </ul> 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 -<p>A {@link android.widget.DatePicker} is a widget that allows the user to select a month, day and year.</p> +<p>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.</p> +<p>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.</p> <ol> - <li>Start a new project/Activity called HelloDatePicker.</li> - <li>Open the layout file and make it like so: - <pre> + <li>Start a new project named <em>HelloDatePicker</em>.</li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: +<pre> <?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> </pre> - <p>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.</p> - </li> - - <li>Open HelloDatePicker.java. Insert the following to the HelloDatePicker class: + <p>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}.</p> + </li> + + <li>Open <code>HelloDatePicker.java</code> and add the following members to the class: <pre> private TextView mDateDisplay; private Button mPickDate; - private int mYear; private int mMonth; private int mDay; static final int DATE_DIALOG_ID = 0; +</pre> + <p>The first group of members define variables for the layout {@link android.view.View}s and the +date items. The <code>DATE_DIALOG_ID</code> is a static integer that uniquely identifies the {@link +android.app.Dialog} that will display the date picker.</p> + </li> - @Override + <li>Now add the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} +method: +<pre> 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(); } </pre> -<p class="note"><strong>Tip:</strong> Press Ctrl(or Cmd) + Shift + O to import all needed packages.</p> - <p>We start by instantiating variables for our Views and date fields. - The <code>DATE_DIALOG_ID</code> is a static integer that uniquely identifies the Dialog. In the - <code>onCreate()</code> 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 <code>showDialog()</code> method will pop-up the date picker dialog - by calling the <code>onCreateDialog()</code> 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 - <code>updateDisplay()</code>—our own method (defined later) that will fill the TextView.</p> -</li> -<li>After the <code>onCreate()</code> method, add the <code>onCreateDialog()</code> callback method -(which is called by <code>showDialog()</code>) -<pre> -@Override -protected Dialog onCreateDialog(int id) { - switch (id) { - case DATE_DIALOG_ID: - return new DatePickerDialog(this, - mDateSetListener, - mYear, mMonth, mDay); - } - return null; -} -</pre> - <p>This method is passed the identifier we gave <code>showDialog()</code> and initializes - the DatePicker to the date we retrieved from our Calendar instance.</p> +<p>First, the content is set to the <code>main.xml</code> 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 +<code>updateDisplay()</code> method is called in order to fill the {@link android.widget.TextView} +with the current date.</p> </li> -<li>Following that, add the <code>updateDisplay()</code> method: +<li>Add the <code>updateDisplay()</code> method: <pre> - // 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(" ")); } </pre> -<p>This uses the member date values to write the date to our TextView.</p> +<p>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.</p> </li> -<li>Finally, add a listener that will be called when the user sets a new date: + +<li>Initialize a new {@link android.app.DatePickerDialog.OnDateSetListener} as a member of the +<code>HelloDatePicker</code> class: <pre> // 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) { } }; </pre> - <p>This <code>OnDateSetListener</code> 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 <code>updateDisplay()</code>.</p> +<p>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 <code>updateDisplay()</code> +method to update the {@link android.widget.TextView}.</p> +</li> + +<li>Now add the {@link android.app.Activity#onCreateDialog(int)} callback method to the {@code +HelloDatePicker} class: +<pre> +@Override +protected Dialog onCreateDialog(int id) { + switch (id) { + case DATE_DIALOG_ID: + return new DatePickerDialog(this, + mDateSetListener, + mYear, mMonth, mDay); + } + return null; +} +</pre> +<p>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.</p> </li> -<li>Now run it.</li> +<li>Run the application.</li> </ol> <p>When you press the "Change the date" button, you should see the following:</p> <img src="images/hello-datepicker.png" width="150px" /> <h3>References</h3> <ul> -<li>{@link android.widget.DatePicker}</li> +<li>{@link android.app.DatePickerDialog}</li> +<li>{@link android.app.DatePickerDialog.OnDateSetListener}</li> <li>{@link android.widget.Button}</li> <li>{@link android.widget.TextView}</li> <li>{@link java.util.Calendar}</li> diff --git a/docs/html/resources/tutorials/views/hello-formstuff.jd b/docs/html/resources/tutorials/views/hello-formstuff.jd index da4289c..3dd5f21 100644 --- a/docs/html/resources/tutorials/views/hello-formstuff.jd +++ b/docs/html/resources/tutorials/views/hello-formstuff.jd @@ -1,58 +1,99 @@ -page.title=Hello, Form Stuff +page.title=Form Stuff parent.title=Hello, Views parent.link=index.html @jd:body -<p>This page introduces a variety of widgets, like image buttons, -text fields, checkboxes and radio buttons.</p> +<p>This tutorial introduces a variety of widgets that are useful when creating forms, such as +image buttons, text fields, checkboxes and radio buttons.</p> <ol> - <li>Start a new project/Activity called HelloFormStuff.</li> - <li>Your layout file should have a basic LinearLayout: - <pre> + <li>Start a new project named <em>HelloFormStuff</em>.</li> + <li>Your <code>res/layout/main.xml</code> file should already have a basic {@link +android.widget.LinearLayout}: +<pre> <?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> </pre> - <p>For each widget you want to add, just put the respective View inside here.</p> -</li> + <p>For each widget you want to add, just put the respective View inside this {@link +android.widget.LinearLayout}.</p> + </li> </ol> -<p class="note"><strong>Tip:</strong> As you add new Android code, press Ctrl(or Cmd) + Shift + O -to import all needed packages.</p> +<p>Each section below also assumes that your <code>HelloFormStuff</code> Activity has the following +default implementation of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:</p> +<pre> +public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); +} +</pre> + + +<h2>Custom Button</h2> -<h2>ImageButton</h2> -<p>A button with a custom image on it. -We'll make it display a message when pressed.</p> +<p>In this section, you will create a button with a custom image instead of text, using the {@link +android.widget.Button} widget and an XML file that defines three different images to use for the +different button states. When the button is pressed, a short message will be displayed.</p> + +<img src="images/android_pressed.png" style="float:right;" title="android_pressed.png"/> +<img src="images/android_focused.png" style="float:right;clear:right;" title="android_focused.png"/> +<img src="images/android_normal.png" style="float:right;clear:right;" title="android_normal.png"/> <ol> - <li><img src="images/android.png" align="right"/> - 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.</li> - <li>Open the layout file and, inside the LinearLayout, add the {@link android.widget.ImageButton} element: + <li>Copy the images on the right into the <code>res/drawable/</code> directory of +your project. These will be used for the different button states.</li> + <li>Create a new file in the <code>res/drawable/</code> directory named +<code>android_button.xml</code>. +Insert the following XML: <pre> -<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> </pre> - <p>The source of the button - is from the res/drawable/ directory, where we've placed the android.png.</p> - <p class="note"><strong>Tip:</strong> You can also reference some of the many built-in - images from the Android {@link android.R.drawable} resources, - like <code>ic_media_play</code>, for a "play" button image. To do so, change the source - attribute to <code>android:src="@android:drawable/ic_media_play"</code>.</p> + <p>This defines a single drawable resource, which will change its image based on the current +state of the button. The first <code><item></code> defines +<code>android_pressed.png</code> as the image when the button is pressed (it's been +activated); the second <code><item></code> defines <code>android_focused.png</code> as the image +when the button is focused (when the button is highlighted using the trackball or directional +pad); and the third <code><item></code> defines <code>android_normal.png</code> as the image +for the normal state (when neither pressed nor focused). This XML file now represents a single +drawable resource and when referenced by a {@link android.widget.Button} for its background, +the image displayed will change based on these three states.</p> + <p class="note"><strong>Note:</strong> The order of the <code><item></code> elements is +important. When this drawable is referenced, the <code><item></code>s are traversed in-order to +determine which one is appropriate for the current button state. Because the "normal" image is last, +it is only applied when the conditions <code>android:state_pressed</code> and +<code>android:state_focused</code> have both evaluated false.</li> + <li>Open the <code>res/layout/main.xml</code> file and add the {@link +android.widget.Button} element: +<pre> + <Button + android:id="@+id/button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="10dp" + android:background="@drawable/android_button" /> +</pre> + <p>The <code>android:background</code> attribute specifies the drawable resource to use for the +button background (which, when saved at <code>res/drawable/android.xml</code>, is +referenced as <code>@drawable/android</code>). This replaces the normal background image +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.</p> </li> -<li>To make the button to actually do something, add the following -code at the end of the <code>onCreate()</code> method: + +<li>To make the button do something when pressed, add the following +code at the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method: <pre> -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() { } }); </pre> -<p>This captures our ImageButton from the layout, then adds an on-click listener to it. -The {@link android.view.View.OnClickListener} must define the <code>onClick()</code> method, which -defines the action to be made when the button is clicked. Here, we show a -{@link android.widget.Toast} message when clicked.</p> +<p>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.</p> </li> -<li>Run it.</li> +<li>Now run the application.</li> </ol> <h2>EditText</h2> -<p>A text field for user input. We'll make it display the text entered so far when the "Enter" key is pressed.</p> + +<p>In this section, you will create a text field for user input, using the {@link +android.widget.EditText} widget. Once text has been entered into the field, the "Enter" key will +display the text in a toast message.</p> <ol> - <li>Open the layout file and, inside the LinearLayout, add the {@link android.widget.EditText} element: + <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.EditText} +element (inside the {@link android.widget.LinearLayout}): <pre> -<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"/> </pre> </li> -<li>To do something with the text that the user enters, add the following code -to the end of the <code>onCreate()</code> method: +<li>To do something with the text that the user types, add the following code +to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method: <pre> final EditText edittext = (EditText) findViewById(R.id.edittext); edittext.setOnKeyListener(new OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { - if ((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() { } }); </pre> -<p>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 <code>onKey()</code> 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 <var>true</var> 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).</p> -<li>Run it.</li> +<p>This captures the {@link android.widget.EditText} element from the layout and adds an {@link +android.view.View.OnKeyListener}. The {@link android.view.View.OnKeyListener} must implement the +{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent)} method, which +defines the action to be made when a key is pressed while the widget has focus. In this case, the +method is defined to listen for the Enter key (when pressed down), then pop up a {@link +android.widget.Toast} message with the text that has been entered. The {@link +android.view.View.OnKeyListener#onKey(View,int,KeyEvent)} method should always return +<code>true</code> if the event has been handled, so that the event doesn't bubble-up (which would +result in a carriage return in the text field).</p> +</li> +<li>Run the application.</li> </ol> <h2>CheckBox</h2> -<p>A checkbox for selecting items. We'll make it display the the current state when pressed.</p> + +<p>In this section, you will create a checkbox for selecting items, using the {@link +android.widget.CheckBox} widget. When the checkbox is pressed, a toast message will +indicate the current state of the checkbox.</p> <ol> - <li>Open the layout file and, inside the LinearLayout, add the {@link android.widget.CheckBox} element: + <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.CheckBox} +element (inside the {@link android.widget.LinearLayout}): <pre> -<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" /> </pre> </li> <li>To do something when the state is changed, add the following code -to the end of the <code>onCreate()</code> method: +to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method: <pre> 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() { } }); </pre> -<p>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 <code>onClick()</code> 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.</p> +<p>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.</p> +</li> <li>Run it.</li> </ol> -<p class="note"><strong>Tip:</strong> If you find that you need to change the state -in another way (such as when loading a saved {@link android.preference.CheckBoxPreference}), -use <code>setChecked(true)</code> or <code>toggle()</code>.</p> +<p class="note"><strong>Tip:</strong> If you need to change the state +yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), +use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link +android.widget.CompoundButton#toggle()} method.</p> <h2>RadioButton</h2> -<p>Two mutually-exclusive radio buttons—enabling one disables the other. -When each is pressed, we'll pop up a message.</p> + +<p>In this section, you will create two mutually-exclusive radio buttons (enabling one disables +the other), using the {@link android.widget.RadioGroup} and {@link android.widget.RadioButton} +widgets. When either radio button is pressed, a toast message will be displayed.</p> <ol> - <li>Open the layout file and, inside the LinearLayout, add two {@link android.widget.RadioButton}s, -inside a {@link android.widget.RadioGroup}: + <li>Open the <code>res/layout/main.xml</code> file and add two {@link +android.widget.RadioButton}s, nested in a {@link android.widget.RadioGroup} (inside the {@link +android.widget.LinearLayout}): <pre> -<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> </pre> +<p>It's important that the {@link android.widget.RadioButton}s are grouped together by the {@link +android.widget.RadioGroup} element so that no more than one can be selected at a time. This logic +is automatically handled by the Android system. When one {@link android.widget.RadioButton} within +a group is selected, all others are automatically deselected.</p> </li> -<li>To do something when each is selected, we'll need an OnClickListener. Unlike the other -listeners we've created, instead of creating this one as an anonymous inner class, -we'll create it as a new object. This way, we can re-use the OnClickLIstener for -both RadioButtons. So, add the following code in the HelloFormStuff Activity -(<em>outside</em> the <code>onCreate()</code> method): + +<li>To do something when each {@link android.widget.RadioButton} is selected, you need an +{@link android.view.View.OnClickListener}. In this case, you want the listener to be re-usable, so +add the following code to create a new member in the <code>HelloFormStuff</code> Activity: <pre> -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() { } }; </pre> -<p>Our <code>onClick()</code> 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.</p> -<li>Now, at the bottom of the <code>onCreate()</code> method, add the following: +<p>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.</p> +<li>Now, at the bottom of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method, add +the following: <pre> 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); </pre> -<p>This captures each of the RadioButtons from our layout and adds the newly-created -OnClickListener to each.</p> -<li>Run it.</li> +<p>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.</p> +<li>Run the application.</li> </ol> -<p class="note"><strong>Tip:</strong> 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 <code>setChecked(true)</code> or <code>toggle()</code>.</p> + +<p class="note"><strong>Tip:</strong> If you need to change the state +yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), +use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link +android.widget.CompoundButton#toggle()} method.</p> <h2>ToggleButton</h2> -<p>A button used specifically for toggling something on and off.</p> + +<p>In this section, you'll create a button used specifically for toggling between two +states, using the {@link android.widget.ToggleButton} widget. This widget is an excellent +alternative to radio buttons if you have two simple states that are mutually exclusive ("on" and +"off", for example).</p> <ol> - <li>Open the layout file and, inside the LinearLayout, add the {@link android.widget.ToggleButton} element: + <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.ToggleButton} +element (inside the {@link android.widget.LinearLayout}): <pre> -<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"/> </pre> + <p>The attributes <code>android:textOn</code> and <code>android:textOff</code> specify the text +for the button when the button has been toggled on or off. The default values are "ON" and +"OFF".</p> </li> <li>To do something when the state is changed, add the following code -to the end of the <code>onCreate()</code> method: +to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method: <pre> 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(); } } }); </pre> -<p>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 <code>onClick()</code> 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.</p> -<li>Run it.</li> +<p>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.</p> + +<p>Notice that the {@link android.widget.ToggleButton} handles its own state change between checked +and unchecked, so you just ask which it is.</p> +<li>Run the application.</li> </ol> -<p class="note"><strong>Tip:</strong> By default, the text on the button is "ON" and "OFF", but -you can change each of these with <code>setTextOn(<var>CharSequence</var>)</code> and -<code>setTextOff(<var>CharSequence</var>)</code>. 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 <code>setChecked(true)</code> or <code>toggle()</code>. </p> +<p class="note"><strong>Tip:</strong> If you need to change the state +yourself (such as when loading a saved {@link android.preference.CheckBoxPreference}), +use the {@link android.widget.CompoundButton#setChecked(boolean)} or {@link +android.widget.CompoundButton#toggle()} method.</p> + + + + +<h2>RatingBar</h2> + +<p>In this section, you'll create a widget that allows the user to provide a rating, +with the {@link android.widget.RatingBar} widget.</p> +<ol> + <li>Open the <code>res/layout/main.xml</code> file and add the {@link android.widget.RatingBar} +element (inside the {@link android.widget.LinearLayout}): +<pre> + <RatingBar android:id="@+id/ratingbar" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:numStars="5" + android:stepSize="1.0"/> +</pre> + <p>The <code>android:numStars</code> attribute defines how many stars to display for the rating +bar. The <code>android:stepSize</code> attribute defines the granularity for each +star (for example, a value of <code>0.5</code> would allow half-star ratings). </p> +</li> +<li>To do something when a new rating has been set, add the following code +to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method: +<pre> +final RatingBar ratingbar = (RatingBar) findViewById(R.id.ratingbar); +ratingbar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() { + public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { + Toast.makeText(HelloFormStuff.this, "New Rating: " + rating, Toast.LENGTH_SHORT).show(); + } +}); +</pre> +<p>This captures the {@link android.widget.RatingBar} widget from the layout with {@link +android.app.Activity#findViewById(int)} and then sets an {@link +android.widget.RatingBar.OnRatingBarChangeListener}. The {@link +android.widget.RatingBar.OnRatingBarChangeListener#onRatingChanged(RatingBar,float,boolean) +onRatingChanged()} callback method then defines the action to perform when the user sets a rating. +In this case, a simple {@link android.widget.Toast} message displays the new rating.</p> + +<li>Run the application.</li> +</ol> -<p>If you've added all the form items above, your application should look something like this:</p> +<p>If you've added all the form widgets above, your application should look like this:</p> <img src="images/hello-formstuff.png" width="150px" /> <h3>References</h3> @@ -258,5 +379,6 @@ use <code>setChecked(true)</code> or <code>toggle()</code>. </p> <li>{@link android.widget.CheckBox}</li> <li>{@link android.widget.RadioButton}</li> <li>{@link android.widget.ToggleButton}</li> + <li>{@link android.widget.RatingBar}</li> </ul> diff --git a/docs/html/resources/tutorials/views/hello-gallery.jd b/docs/html/resources/tutorials/views/hello-gallery.jd index 084f912..12d5a91 100644 --- a/docs/html/resources/tutorials/views/hello-gallery.jd +++ b/docs/html/resources/tutorials/views/hello-gallery.jd @@ -1,16 +1,21 @@ -page.title=Hello, Gallery +page.title=Gallery parent.title=Hello, Views parent.link=index.html @jd:body -<p>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.</p> +<p>{@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.</p> + +<p>In this tutorial, you'll create a gallery of photos and then display a toast message each time a +gallery item is selected.</p> <ol> - <li>Start a new project/Activity called HelloGallery.</li> - <li>Add some images to your res/drawable/ directory.</li> - <li>Open the layout file and make it like so: + <li>Start a new project named <em>HelloGallery</em>.</li> + <li>Find some photos you'd like to use, or use these <a +href="{@docRoot}shareables/sample_images.zip">sample images</a>. Save the images into the project's +<code>res/drawable/</code> directory.</li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?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" /> </pre> -</li> - + </li> -<li>Open the HelloGallery.java file. Insert the following for the <code>onCreate()</code> method: +<li>Open the <code>HelloGallery.java</code> file and insert the following code for the +{@link android.app.Activity#onCreate(Bundle) onCreate()} method: <pre> @Override public void onCreate(Bundle savedInstanceState) { @@ -39,19 +44,46 @@ public void onCreate(Bundle savedInstanceState) { }); } </pre> - <p>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 <code>onItemClick()</code> 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 <code>Toast.makeText().show()</code>. + <p>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 +<code>ImageAdapter</code> is +instantiated and applied to the {@link android.widget.Gallery} with {@link +android.widget.AdapterView#setAdapter(T) setAdapter()}. (The <code>ImageAdapter</code> 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). </p> </li> - -<li>After the <code>onCreate()</code> method, add the <code>ImageAdapter</code> class: + <li>Create a new XML file in the <code>res/values/</code> directory named <code>attrs.xml</code>. +Insert the following: +<pre> +<?xml version="1.0" encoding="utf-8"?> +<resources> + <declare-styleable name="HelloGallery"> + <attr name="android:galleryItemBackground" /> + </declare-styleable> +</resources> +</pre> + <p>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 +<code><attr></code> 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.</p> + </li> + + <li>Go back to the <code>HelloGallery.java</code> file. After the {@link + android.app.Activity#onCreate(Bundle)} method, define the custom <code>ImageAdapter</code> class: <pre> public class ImageAdapter extends BaseAdapter { int mGalleryItemBackground; @@ -100,26 +132,30 @@ public class ImageAdapter extends BaseAdapter { } </pre> <p>First, there are a few member variables, including an array of IDs that reference -the images we placed in our drawable resources directory.</p> -<p>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 <code>mGalleryItemBackground</code>, it's important to recycle the -StyledAttribute for later re-use.</p> -<p>The next three methods are required for basic member queries. -But then we have the <code>getView()</code> 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.</p> - -<p>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.</p> - -<li>Now run it.</li> +the images saved in the drawable resources directory ({@code res/drawable/}).</p> +<p>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.</p> +<p>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.</p> + +<p>See {@link android.widget.ImageView.ScaleType} for other image scaling options.</p> +</li> + +<li>Run the application.</li> </ol> + <p>You should see something like this:</p> <img src="images/hello-gallery.png" width="150px" /> @@ -129,7 +165,7 @@ exactly match the ImageView dimensions.</p> <li>{@link android.widget.BaseAdapter}</li> <li>{@link android.widget.Gallery}</li> <li>{@link android.widget.ImageView}</li> - <li>{@link android.widget.Toast}</li> + <li>{@link android.widget.AdapterView.OnItemClickListener}</li> </ul> diff --git a/docs/html/resources/tutorials/views/hello-gridview.jd b/docs/html/resources/tutorials/views/hello-gridview.jd index ffb6c93..03bfc54 100644 --- a/docs/html/resources/tutorials/views/hello-gridview.jd +++ b/docs/html/resources/tutorials/views/hello-gridview.jd @@ -1,33 +1,44 @@ -page.title=Hello, GridView +page.title=Grid View parent.title=Hello, Views parent.link=index.html @jd:body -<p>A {@link android.widget.GridView} displays items in a two-dimensional, scrolling grid. The items -are acquired from a {@link android.widget.ListAdapter}.</p> +<p>{@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}.</p> + +<p>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.</p> <ol> - <li>Start a new project/Activity called HelloGridView.</li> - <li>Find some photos you'd like to use, or copy some from the SDK samples res/drawable/ - folder of your project.</li> - <li>Open the layout and make it like so: + <li>Start a new project named <em>HelloGridView</em>.</li> + <li>Find some photos you'd like to use, or <a +href="{@docRoot}shareables/sample_images.zip">download these sample images</a>. Save the image files +into the project's +<code>res/drawable/</code> directory.</li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?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" /> </pre> + <p>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.</p> </li> - <li>Open the HelloGridView Java file. Insert the following for the <code>onCreate()</code> method: + <li>Open <code>HelloGridView.java</code> and insert the following code for the +{@link android.app.Activity#onCreate(Bundle) onCreate()} method: <pre> 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(); + } + }); } </pre> - <p>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.</p> + <p>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.</p> +<p>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).</p> + </li> -<li>Create a new class (nested or otherwise), called ImageAdapter, which extends {@link android.widget.BaseAdapter}: +<li>Create a new class called <code>ImageAdapter</code> that extends {@link +android.widget.BaseAdapter}: <pre> public class ImageAdapter extends BaseAdapter { private Context mContext; @@ -93,37 +125,58 @@ public class ImageAdapter extends BaseAdapter { }; } </pre> - <p>First we take care of some required methods inherited from BaseAdapter. - The constructor and <code>getCount()</code> are self-explanitory. Normally, <code>getItem()</code> - should return the actual object at the specified position in our Adapter, but for this Hello World, - we're not going to bother. Likewise, <code>getItemId()</code> should return the row id of - the item, but right now we don't care.</p> - <p>However, <code>getView()</code> 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 <code>LayoutParams()</code> 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 <code>setScaleType()</code>, 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 <code>getView()</code> we set the image resource and - return the ImageView.</p> - <p>All that's left is our array or drawable resources at the bottom.</p> +<p>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.</p> + +<p>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 <em>is</em> null, an {@link android.widget.ImageView} is instantiated and +configured with desired properties for the image presentation:</p> +<ul> + <li>{@link android.view.View#setLayoutParams(ViewGroup.LayoutParams)} sets +the height and width for the View—this ensures that, no matter the size of the drawable, each +image is resized and cropped to fit in these dimensions, as appropriate.</li> + <li>{@link android.widget.ImageView#setScaleType(ImageView.ScaleType)} declares that images should +be cropped toward the center (if necessary).</li> + <li>{@link android.widget.ImageView#setPadding(int,int,int,int)} defines the padding for all +sides. (Note that, if the images have different aspect-ratios, then less +padding will cause for more cropping of the image if it does not match +the dimensions given to the ImageView.)</li> +</ul> + +<p>If the {@link android.view.View} passed to {@link +android.widget.Adapter#getView(int,View,ViewGroup) getView()} is <em>not</em> null, then the local +{@link android.widget.ImageView} is initialized with the recycled {@link android.view.View} +object.</p> + +<p>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}.</p> +<p>All that's left is to define the {@code mThumbIds} array of drawable resources.</p> </li> -<li>Run it.</li> +<li>Run the application.</li> </ol> <p>Your grid layout should look something like this:</p> <img src="images/hello-gridview.png" width="150px" /> -<p>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)}. </p> +<p>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)}. </p> <h3>References</h3> <ul> <li>{@link android.widget.GridView}</li> <li>{@link android.widget.ImageView}</li> <li>{@link android.widget.BaseAdapter}</li> + <li>{@link android.widget.AdapterView.OnItemClickListener}</li> </ul> diff --git a/docs/html/resources/tutorials/views/hello-linearlayout.jd b/docs/html/resources/tutorials/views/hello-linearlayout.jd index 0e8947c..8e072b1 100644 --- a/docs/html/resources/tutorials/views/hello-linearlayout.jd +++ b/docs/html/resources/tutorials/views/hello-linearlayout.jd @@ -1,16 +1,18 @@ -page.title=Hello, LinearLayout +page.title=Linear Layout parent.title=Hello, Views parent.link=index.html @jd:body -<p>A {@link android.widget.LinearLayout} is a GroupView that will lay child View elements -vertically or horizontally.</p> +<p>{@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.</p> +<p>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.</p> <ol> - <li>Start a new project/Activity called HelloLinearLayout.</li> - <li>Open the layout file. - Make it like so: + <li>Start a new project named <em>HelloLinearLayout</em>.</li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" @@ -18,113 +20,114 @@ vertically or horizontally.</p> 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> </pre> - <p>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.</p> + +<p>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}.</p> </li> -<li>Now open the HelloLinearLayout Activity and be sure it loads this layout in the <code>onCreate()</code> method:</p> +<li>Now open <code>HelloLinearLayout.java</code> and be sure it loads the +<code>res/layout/main.xml</code> layout in the +{@link android.app.Activity#onCreate(Bundle) onCreate()} method:</p> <pre> public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } </pre> -<p><code>R.layout.main</code> refers to the <code>main.xml</code> layout file.</p> +<p>The {@link android.app.Activity#setContentView(int)} method loads the +layout file for the {@link android.app.Activity}, specified by the resource +ID — <code>R.layout.main</code> refers to the <code>res/layout/main.xml</code> layout +file.</p> </li> -<li>Run it.</li> +<li>Run the application.</li> </ol> <p>You should see the following:</p> <img src="images/hello-linearlayout.png" width="150px" /> -<p>Notice how the various XML attributes define the View's behavior. -Pay attention to the effect of the <code>layout_weight</code>. Try - experimenting with different values to see how the screen real estate is - distributed based on the weight of each element.</p> +<p>Notice how the XML attributes define each View's behavior. Try +experimenting with different values for <code>android:layout_weight</code> to see how the screen +real estate is distributed based on the weight of each element. See the <a +href="{@docRoot}guide/topics/ui/layout-objects.html#linearlayout">Common Layout Objects</a> +document for more about how {@link android.widget.LinearLayout} handles the +<code>android:layout_weight</code> attribute.</p> <h3>References</h3> <ul> <li>{@link android.widget.LinearLayout}</li> -<li>{@link android.widget.TextView}</li> + <li>{@link android.widget.TextView}</li> </ul> diff --git a/docs/html/resources/tutorials/views/hello-listview.jd b/docs/html/resources/tutorials/views/hello-listview.jd index d90005b..194258e 100644 --- a/docs/html/resources/tutorials/views/hello-listview.jd +++ b/docs/html/resources/tutorials/views/hello-listview.jd @@ -1,36 +1,88 @@ -page.title=Hello, ListView +page.title=List View parent.title=Hello, Views parent.link=index.html @jd:body -<p>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}.</p> +<p>{@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}.</p> +<p>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.</p> <ol> - <li>Start a new project/ListActivity called HelloListView.</li> - <li>Open the HelloListView Java file. Make the class extend ListActivity (instead of Activity). + <li>Start a new project named <em>HelloListView</em>.</li> + <li>Create an XML file named <code>list_item.xml</code> and save it inside the +<code>res/layout/</code> folder. Insert the following: +<pre> +<?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> +</pre> + <p>This file defines the layout for each item that will be placed in the {@link +android.widget.ListView}.</p> + </li> + + <li>Open the <code>HelloListView.java</code> and make the class extend {@link +android.app.ListActivity} (instead of {@link android.app.Activity}): <pre>public class HelloListView extends ListActivity {</pre> </li> - <li>Insert the following for the <code>onCreate()</code> method: + <li>Insert the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} +method: <pre> @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(); + } + }); } </pre> - <p>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 <code>setListAdapter()</code> (which automatically - adds a ListView to the ListActivity), and provide it with an ArrayAdapter that binds a - <code>simple_list_item_1</code> layout item to each entry in the <code>COUNTRIES</code> - 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.</p> - </li> - <li>Following the <code>onCreate()</code> method, add the String array: +<p>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).</p> + +<p>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.</p> + +<p>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.</p> + +<p class="note"><strong>Tip:</strong> 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 <code>android.R.layout.simple_list_item_1</code> instead of +<code>R.layout.list_item</code>.</p> +</li> + +<li>After the {@link android.app.Activity#onCreate(Bundle) onCreate()} method, add the string +array: <pre> 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" }; </pre> + <p>This is the array of strings that will be placed into the {@link android.widget.ListView}.</p> </li> -<li> Run it.</li> +<li>Run the application.</li> </ol> -<p>You can scroll the list, or type to filter it. You should see something like this:</p> +<p>You can scroll the list, or type to filter it, then click an item to see a message. You +should see something like this:</p> <img src="images/hello-listview.png" width="150px" /> +<p>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:</p> +<pre> +<?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> +</pre> +<p>To use these resource strings for the {@link android.widget.ArrayAdapter}, replace the original +{@link android.app.ListActivity#setListAdapter(ListAdapter)} line with the following:</p> +<pre> +String[] countries = getResources().getStringArray(R.array.countries_array); +setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, countries)); +</pre> + <h3>References</h3> <ul> <li>{@link android.widget.ListView}</li> diff --git a/docs/html/resources/tutorials/views/hello-mapview.jd b/docs/html/resources/tutorials/views/hello-mapview.jd index 531300f..a3fa548 100644 --- a/docs/html/resources/tutorials/views/hello-mapview.jd +++ b/docs/html/resources/tutorials/views/hello-mapview.jd @@ -1,273 +1,303 @@ -page.title=Hello, MapView +page.title=Google Map View parent.title=Hello, Views parent.link=index.html @jd:body +<p>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.</p> + <div class="special"> -<p>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:</p> - -<p style="margin-left:2em;"><a -href="http://code.google.com/android/add-ons/google-apis">http://code.google.com/android/add-ons/google-apis</a></p> - -<p>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 +<p>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 <a href="{@docRoot}sdk/adding-components.html">Adding SDK +Components</a>.</p> + +<p>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 <a href="{@docRoot}guide/developing/eclipse-adt.html">Developing in Eclipse with ADT</a> or <a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>, as appropriate for your environment. </p> -<p>You will also need to use the android tool to set up an AVD that uses the -Google APIs deployment target. See <a +<p>You will also need to set up a new AVD that uses the same Google APIs deployment target. See <a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a> for -more information. Once you have set up your environment, you will be able to -build and run the project described in this tutorial</a></p> +more information.</p> + +<p>For reference material, see the <a +href="http://code.google.com/android/add-ons/google-apis/reference/index.html">Google Maps +library documentation</a>.</p> </div> -<p>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.</p> +<h2>Part 1: Creating a Map Activity</h2> <ol> - <li>Start a new project/Activity called HelloMapView. - - <li>Because we're using the Google Maps library, - which is not a part of the standard Android library, we need to - declare it in the Android Manifest. Open the AndroidManifest.xml - file and add the following as a child of the <code><application></code> element: - - <pre><uses-library android:name="com.google.android.maps" /></pre> - </li> - <li>We also need access to the internet in order to retrieve the Google Maps tiles, - so the application must request the {@link android.Manifest.permission#INTERNET INTERNET} permissions. - In the manifest file, add the following as a child of the <code><manifest></code> element: - <pre><uses-permission android:name="android.permission.INTERNET" /></pre> - </li> - <li>Now open the main layout file for your project. Define a layout with a com.google.android.maps.MapView - inside a android.widget.RelativeLayout: + <li>Start a new project named <em>HelloGoogleMaps</em>.</li> + + <li>Because the Maps library is not a part of the standard Android library, you must + declare it in the Android Manifest. Open the <code>AndroidManifest.xml</code> + file and add the following as a child of the <code><application></code> element: + <pre><uses-library android:name="com.google.android.maps" /></pre> + </li> + + <li>You also need access to the Internet in order to retrieve map tiles, + so you must also request the {@link android.Manifest.permission#INTERNET} permission. + In the manifest file, add the following as a child of the <code><manifest></code> element: + <pre><uses-permission android:name="android.permission.INTERNET" /></pre> + </li> + + <li>While you're in the manifest, give the map some more space by getting rid of the title bar +with the "NoTitleBar" theme: +<pre> +<activity android:name=".HelloGoogleMaps" android:label="@string/app_name" + <strong>android:theme="@android:style/Theme.NoTitleBar"</strong>> +</pre> + </li> + + <li>Open the <code>res/layout/main.xml</code> file and add a single + {@code com.google.android.maps.MapView} as the root node: <pre> <?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="<em>Your Maps API Key</em>" - /> - -</RelativeLayout> + android:layout_height="fill_parent" + android:clickable="true" + android:apiKey="<em>Your Maps API Key goes here</em>" +/> </pre> - <p>The <code>clickable</code> 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.</p> - - <p>The <code>apiKey</code> 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 - <a href="http://code.google.com/android/add-ons/google-apis/mapkey.html">Obtaining a Maps API Key</a>. - (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 <code>apiKey</code> value.</p></li> - - <li>Now open the HelloMapView.java file. For this Activity, we're going to extend the special sub-class of - Activity called MapActivity, so change the class declaration to extend - MapActicity, instead of Activity:</p> - - <pre>public class HelloMapView extends MapActivity {</pre> - - <li>The <code>isRouteDisplayed()</code> method is required, so add it inside the class: + <p>The <code>android:clickable</code> attribute defines whether you want to allow + user-interaction with the map. If this is "false" then touching the map does nothing.</p> + + <p>The <code>android:apiKey</code> 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.</p> + <p>Go now to get a key. For instructions, read + <a href="http://code.google.com/android/add-ons/google-apis/mapkey.html">Obtaining a Maps API + Key</a>. For the purpose of this tutorial, you should <a + href="http://code.google.com/android/add-ons/google-apis/mapkey.html#getdebugfingerprint">register + with the SDK debug certificate</a>, 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 <code>android:apiKey</code>.</p> + </li> + + <li>Now open the <code>HelloGoogleMaps.java</code> file. For this Activity, extend + {@code MapActivity} (instead of {@code android.app.Activity}):</p> + + <pre>public class HelloGoogleMaps extends MapActivity {</pre> + <p>This is a special sub-class of {@link android.app.Activity}, provided by the Maps + library, which provides important map capabilities.</p> + + <li>Inside every {@code MapActivity}, the <code>isRouteDisplayed()</code> method is required, so + override this method: <pre> @Override protected boolean isRouteDisplayed() { return false; } </pre> -<p>You can actually run this now, but all it does is allow you to pan around the map.</p> -<p>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 <code>getZoomControls()</code> -method. Let's do this.</p> +<p>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.</p> +</li> -<li>Go back to the layout file. We need a new ViewGroup element, in which we'll - place the ZoomControls. Just below the MapView element (but inside the RelativeLayout), add this element: +<li>Now add the standard {@link android.app.Activity#onCreate(Bundle) onCreate()} callback method +to the class: <pre> -<LinearLayout - android:id="@+id/zoomview" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignBottom="@id/mapview" - android:layout_centerHorizontal="true" -/></pre> - - <p>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.</p> - - <p>The last two attributes are available only to an element that's a child of a - RelativeLayout. <code>layout_alignBottom</code> 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). - <code>layout_centerHorizontal</code> centers this on the horizontal plane.</p></li> - - <li>Now go back to the HelloMapView class. We'll now retrieve the ZoomControls object from - the MapView and add it to our new layout element. First, at the top of the HelloMapView, - instantiate handles for the MapView and LinearLayout, plus a ZoomControl object: -<pre> -LinearLayout linearLayout; -MapView mapView; -ZoomControls mZoom;</pre></li> - - <li>Then initialize each of these in <code>onCreate()</code>. 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); +} +</pre> +<p>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:</p> <pre> -linearLayout = (LinearLayout) findViewById(R.id.zoomview); -mapView = (MapView) findViewById(R.id.mapview); -mZoom = (ZoomControls) mapView.getZoomControls();</pre> - - <p>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.</p></li> - - <li>Now just plug our ZoomControls into the LinearLayout we added: - - <pre>linearLayout.addView(mZoom);</pre></li> - - <li>Run it.</li> + MapView mapView = (MapView) findViewById(R.id.mapview); + mapView.setBuiltInZoomControls(true); +</pre> +</li> +<li>That's all there is to it. Run the application. (Remember, you must have an <a +href="{@docRoot}guide/developing/tools/avd.html">AVD</a> configured to use the Google APIs +target, or be using a development device that includes the Maps library.)</li> </ol> -<hr/> +<h2>Part 2: Adding Overlay Items</h2> -<p>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.</p> +<p>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).</p> <ol> - <li>Create a new Java class named HelloItemizedOverlay that implements ItemizedOverlay. - - <p>When using Eclipse, right-click the package name in the Eclipse Package Explorer, and select New > Class. Fill-in - the Name field as <em>HelloItemizedOverlay</em>. For the Superclass, enter - <em>com.google.android.maps.ItemizedOverlay</em>. Click the checkbox for <em>Constructors from - superclass</em>. Click Finish.</p></li> - - <li> First thing, we need an OverlayItem ArrayList, in which we'll put each of the OverlayItem - objects we want on our map. Add this at the top of the HelloItemizedOverlay class: - - <pre>private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();</pre></li> - - <li>All the constructor does is define the default marker to be used on each of the OverlayItems. - In order for the Drawable to actually get drawn, it must have its bounds defined. And we want the - center-point at the bottom of the image to be the point at which it's attached to the map - coordinates. We handle all this with the boundCenterBottom() method. Wrap this around our - defaultMarker, so the super constructor call looks like this: - - <pre>super(boundCenterBottom(defaultMarker));</pre></li> - - <li>In order to add new OverlayItems to our ArrayList, we need a new public method. We'll handle - this with the following method: + <li>Create a new Java class named <code>HelloItemizedOverlay</code> that implements + {@code ItemizedOverlay}. + + <p>When using Eclipse, right-click the package name in the Eclipse Package Explorer, and + select <strong>New > Class</strong>. Fill-in + the Name field as <em>HelloItemizedOverlay</em>. For the Superclass, enter + "com.google.android.maps.ItemizedOverlay". Click the checkbox for <em>Constructors from + superclass</em>. Click Finish.</p></li> + + <li>First, you need an <code>OverlayItem</code> {@link java.util.ArrayList}, in which you'll put + each of the <code>OverlayItem</code> objects you want on the map. Add this at the top of the + <code>HelloItemizedOverlay</code> class: + + <pre>private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();</pre> + </li> + + <li>Now define the <code>HelloItemizedOverlay</code> 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: +<pre> +public HelloItemizedOverlay(Drawable defaultMarker) { + super(boundCenterBottom(defaultMarker)); +} +</pre> + </li> + <li>In order to add new {@code OverlayItem}s to the ArrayList, you need a new method: <pre> public void addOverlay(OverlayItem overlay) { mOverlays.add(overlay); populate(); }</pre> + <p>Each time you add a new {@code OverlayItem} to the ArrayList, you must call + <code>populate()</code> for the {@code ItemizedOverlay}, which will read each of the + {@code OverlayItem}s and prepare them to be drawn.</p> + </li> - <p>Each time we add a new OverlayItem, we must call <code>populate()</code>, which will read each of out - OverlayItems and prepare them to be drawn.</p></li> - - <li>In order for the <code>populate()</code> method to read each OverlayItem, it will make a request to - <code>createItem(int)</code>. We must define this method to properly read from our ArrayList. Replace the - existing contents of the createItem method with a <code>get()</code> call to our ArrayList: + <li>When the <code>populate()</code> method executes, it will call <code>createItem(int)</code> 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: <pre> @Override protected OverlayItem createItem(int i) { return mOverlays.get(i); } -</pre></li> - - <li>We're also required to override the <code>size()</code> method. Replace the existing contents of the - method with a size request to our ArrayList: +</pre> + </li> - <pre>return mOverlays.size();</pre></li> -</ol> + <li>You must also override the <code>size()</code> method to return the current number of + items in the ArrayList: +<pre> +@Override +public int size() { + return mOverlays.size(); +} +</pre> + </li> + <li>Now set up the ability to handle touch events on the overlay items. First, you're + going to need a reference to the application {@link android.content.Context} as a member of + this class. So add {@code Context mContext} as a class member, then initialize it with a + new class constructor: +<pre> +public HelloItemizedOverlay(Drawable defaultMarker, Context context) { + super(defaultMarker); + mContext = context; +} +</pre> + <p>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}.</p> -<p>That's it for the HelloItemizedOverlay class. We're now ready to use it.</p> + <p>Then override the {@code onTap(int)} callback method, which will handle the event + when an item is tapped by the user:</p> +<pre> +@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; +} +</pre> + <p>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.)</p> + </li> -<hr/> -<p>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.</p> +</ol> -<img src="images/androidmarker.png" align="right" /> -<p>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.</p> +<p>You're now done with the <code>HelloItemizedOverlay</code> class and can start using it +to add items on the map.</p> -<p>Now we're ready to work in the HelloMapView:</p> +<p>Go back to the <code>HelloGoogleMaps</code> class. In the following procedure, you'll create an +{@code OverlayItem} and add it to an instance of the <code>HelloItemizedOverlay</code> class, then +add the <code>HelloItemizedOverlay</code> to the <code>MapView</code> using a {@code GeoPoint} +to define its coordinates on the map.</p> +<img src="images/androidmarker.png" align="right" /> <ol> - <li>First we need some more types. Add the following at the top of the HelloMapView class: - -<pre> -List<Overlay> mapOverlays; -Drawable drawable; -HelloItemizedOverlay itemizedOverlay;</pre></li> + <li>First, you need the image for the map overlay. If you don't have one handy, use the Android on + the right. Drag this image (or your own) into the <code>res/drawable/</code> directory of your + project.</li> - <li>Now pick up where we left off in the <code>onCreate()</code> method. Instantiate the - new fields: + <li>At the end of your existing {@code onCreate()} method, instantiate : <pre> -mapOverlays = mapView.getOverlays(); -drawable = this.getResources().getDrawable(R.drawable.androidmarker); -itemizedoverlay = new HelloItemizedOverlay(drawable);</pre> - - <p>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 <code>getOverlays()</code> 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.</p></li> - - <li>Now let's make our first OverlayItem by creating a GeoPoint - that defines our map coordinates, then pass it to a new OverlayItem: - +List<Overlay> mapOverlays = mapView.getOverlays(); +Drawable drawable = this.getResources().getDrawable(R.drawable.androidmarker); +HelloItemizedOverlay itemizedoverlay = new HelloItemizedOverlay(drawable);</pre> + + <p>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 <code>getOverlays()</code> 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.</p> + </li> + + <li>Now create a {@code GeoPoint} that defines the map coordinates for the first overlay item, + and pass it to a new {@code OverlayItem}: <pre> GeoPoint point = new GeoPoint(19240000,-99120000); -OverlayItem overlayitem = new OverlayItem(point, "", "");</pre> - - <p>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.</p></li> +OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!", "I'm in Mexico City!"); +</pre> - <li>All that's left is for us to add this OverlayItem to our collection in the HelloItemizedOverlay, - and add this to the List of Overlay objects retrieved from the MapView: + <p>{@code GeoPoint} coordinates are specified in microdegrees (<code>degrees * 1e6</code>). 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.</p> + </li> + <li>All that's left is to add this {@code OverlayItem} to your collection in the + {@code HelloItemizedOverlay} instance, then add the {@code HelloItemizedOverlay} to the MapView: <pre> itemizedoverlay.addOverlay(overlayitem); -mapOverlays.add(itemizedoverlay);</pre></li> +mapOverlays.add(itemizedoverlay); +</pre> + </li> - <li>Run it!</li> + <li>Now run the application.</li> </ol> -<p>We've sent our droid to Mexico City. Hola, Mundo!</p> <p>You should see the following:</p> <img src="images/hello-mapview.png" width="150px" /> +<p>When you tap the overlay item, you'll see the dialog appear.</p> -<p>Because we created our ItemizedOverlay class with an ArrayList, we can continue adding new -OverlayItems. Try adding another one. Before the <code>addOverlay()</code> method is called, add these lines:</p> +<p>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 +<code>addOverlay()</code> method is called, add these lines:</p> <pre> GeoPoint point2 = new GeoPoint(35410000, 139460000); -OverlayItem overlayitem2 = new OverlayItem(point2, "", ""); +OverlayItem overlayitem2 = new OverlayItem(point2, "Sekai, konichiwa!", "I'm in Japan!"); </pre> -<p>Run it again... We've sent a new droid to Tokyo. Sekai, konichiwa!</p> +<p>Run the application again. (You probably need to move the map to find the new overlay item.)</p> 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 -<p>A {@link android.widget.RelativeLayout} is a ViewGroup that allows you to layout child elements -in positions relative to the parent or siblings elements.</p> +<p>{@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).</p> + +<p>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}.</p> <ol> - <li>Start a new project/Activity called HelloRelativeLayout.</li> - <li>Open the layout file. Make it like so: + <li>Start a new project named <em>HelloRelativeLayout</em>.</li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?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.</p> 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> </pre> -<p>Pay attention to each of the additional <code>layout_*</code> attributes (besides the -usual width and height, which are required for all elements). When using relative layout, -we use attributes like <code>layout_below</code> and <code>layout_toLeftOf</code> 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.</p> +<p>Notice each of the <code>android:layout_*</code> attributes, such as <code>layout_below</code>, +<code>layout_alignParentRight</code>, and <code>layout_toLeftOf</code>. 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 <code>ok</code> (which is the previous {@link android.widget.Button}).</p> +<p>All of the available layout attributes are defined in {@link +android.widget.RelativeLayout.LayoutParams}.</p> </li> -<li>Make sure your Activity loads this layout in the <code>onCreate()</code> method:</p> +<li>Make sure you load this layout in the +{@link android.app.Activity#onCreate(Bundle) onCreate()} method:</p> <pre> public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } </pre> -<p><code>R.layout.main</code> refers to the <code>main.xml</code> layout file.</p> +<p>The {@link android.app.Activity#setContentView(int)} method loads the +layout file for the {@link android.app.Activity}, specified by the resource +ID — <code>R.layout.main</code> refers to the <code>res/layout/main.xml</code> layout +file.</p> </li> -<li>Run it.</li> +<li>Run the application.</li> </ol> -<p>You should see the following:</p> +<p>You should see the following layout:</p> <img src="images/hello-relativelayout.png" width="150px" /> <h3>Resources</h3> <ul> <li>{@link android.widget.RelativeLayout}</li> + <li>{@link android.widget.RelativeLayout.LayoutParams}</li> <li>{@link android.widget.TextView}</li> <li>{@link android.widget.EditText}</li> <li>{@link android.widget.Button}</li> diff --git a/docs/html/resources/tutorials/views/hello-spinner.jd b/docs/html/resources/tutorials/views/hello-spinner.jd index 3a04214..7a3a9c3 100644 --- a/docs/html/resources/tutorials/views/hello-spinner.jd +++ b/docs/html/resources/tutorials/views/hello-spinner.jd @@ -1,17 +1,17 @@ -page.title=Hello, Spinner +page.title=Spinner parent.title=Hello, Views parent.link=index.html @jd:body -<p>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.</p> +<p>{@link android.widget.Spinner} is a widget similar to a drop-down list for selecting items.</p> +<p>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.</p> <ol> - <li>Start a new project/Activity called HelloSpinner.</li> - <li>Open the layout file. - Make it like so: + <li>Start a new project named <em>HelloSpinner</em>.</li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?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.</p> 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> </pre> - <p>Notice that the Spinner's <code>android:prompt</code> 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...</p> -</li> - -<li>Open the strings.xml file in res/values/ and add the following <code><string></code> -element inside the <code><resources></code> element: -<pre> -<string name="planet_prompt">Choose a planet</string> -</pre> + <p>Notice that the {@link android.widget.TextView}'s <code>android:text</code> attribute and the +{@link android.widget.Spinner}'s <code>android:prompt</code> 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.</p> </li> -<li>Create a new XML file in res/values/ called arrays.xml. Insert the following: +<li>Create a <code>strings.xml</code> file in <code>res/values/</code> and edit the file to look +like this: <pre> +<?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 <code><resources></code> element: <item>Uranus</item> <item>Neptune</item> </string-array> - </resources> </pre> - <p>This is the list of items (planets) that the user can select from in the Spinner widget.</p> + <p>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.</p> </li> -<li>Now open the HelloSpinner.java file. Insert the following code into the HelloSpinner class: +<li>Now open the <code>HelloSpinner.java</code> file and insert the following code for the {@link +android.app.Activity#onCreate(Bundle) onCreate()} method: <pre> @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); - Spinner s = (Spinner) findViewById(R.id.spinner); - ArrayAdapter<CharSequence> 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); +} +</pre> + <p>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)}.</p> +</li> + +<li>Now create a nested class that implements {@link +android.widget.AdapterView.OnItemSelectedListener}. This will provide a callback method that will +notify your application when an item has been selected from the {@link +android.widget.Spinner}. Here's what this class should look like: +<pre> +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. + } } </pre> - <p>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 <code>createFromResource</code> our Context, - the array of selectable items and the type of layout we'd like each one bound to. We then call - <code>setDropDownViewResource()</code> 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.</p> +<p>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.</p> +</li> + +<li>Now the {@code MyOnItemSelectedListener} needs to be applied to the {@link +android.widget.Spinner}. Go back to the {@link android.app.Activity#onCreate(Bundle) onCreate()} +method and add the following line to the end: +<pre> + spinner.setOnItemSelectedListener(new MyOnItemSelectedListener()); +</pre> +<p>This creates a new anonymous instance of the {@code MyOnItemSelectedListener} and sets it as the +listener for the {@link android.widget.Spinner}.</p> </li> -<li>Now run it.</li> +<li>Run the application.</li> </ol> <p>It should look like this:</p> <img src="images/hello-spinner.png" width="150px" /> 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 -<p>A {@link android.widget.TableLayout} is a ViewGroup that -will lay child View elements into rows and columns.</p> +<p>{@link android.widget.TableLayout} is a {@link android.view.ViewGroup} that +displays child {@link android.view.View} elements in rows and columns.</p> <ol> - <li>Start a new project/Activity called HelloTableLayout.</li> - <li>Open the layout file. - Make it like so: + <li>Start a new project named <em>HelloTableLayout</em>.</li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?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.</p> </TableRow> </TableLayout> </pre> -<p>Notice how this resembles the structure of an HTML table. <code>TableLayout</code> is like the -<code>table</code> element; <code>TableRow</code> is like a <code>tr</code> element; but for our cells like -the html <code>td</code> element, we can use any kind of View. Here, we use <code>TextView</code> for the cells.</p> +<p>Notice how this resembles the structure of an HTML table. The {@link android.widget.TableLayout} +element is like the HTML <code><table></code> element; {@link android.widget.TableRow} is like +a <code>><tr>></code> 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.</p> </li> -<li>Make sure your Activity loads this layout in the <code>onCreate()</code> method: +<li>Make sure your <em>HelloTableLayout</em> Activity loads this layout in the +{@link android.app.Activity#onCreate(Bundle) onCreate()} method: <pre> public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } </pre> -<p><code>R.layout.main</code> refers to the <code>main.xml</code> layout file.</p> +<p>The {@link android.app.Activity#setContentView(int)} method loads the +layout file for the {@link android.app.Activity}, specified by the resource +ID — <code>R.layout.main</code> refers to the <code>res/layout/main.xml</code> layout +file.</p> </li> -<li>Run it.</li> +<li>Run the application.</li> </ol> <p>You should see the following:</p> <img src="images/hello-tablelayout.png" width="150px" /> 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 -<p>A {@link android.widget.TabWidget} offers the ability to easily draw an interface that uses -tabs to navigate between different views.</p> +<p>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.</p> + +<p>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.</p> + +<p>In this tutorial, you'll create a tabbed UI that uses a separate {@link +android.app.Activity} for each tab.</p> <ol> - <li>Start a new project/Activity called HelloTabWidget.</li> - <li>Open the layout file and make it like so:</li> + <li>Start a new project named <em>HelloTabWidget</em>.</li> + <li>First, create three separate {@link android.app.Activity} classes in your project: +<code>ArtistsActivity</code>, <code>AlbumsActivity</code>, and <code>SongsActivity</code>. These +will each represent a separate tab. For now, make each one display a simple message using a {@link +android.widget.TextView}. For example: +<pre> +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); + } +} +</pre> + <p>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.</p> + + <li>You're going to need an icon for each of your tabs. And for each one, you should create an +image for two different states: one for when the tab is selected, and one for when it is not. The +general design recommendation is for the selected tab icon to be a darker color (grey), and the +non-selected icon to be lighter (white). For example: + <p> + <img src="images/ic_tab_artists_white.png" title="ic_tab_artists_white.png" alt="" /> + <img src="images/ic_tab_artists_grey.png" title="ic_tab_artists_grey.png" alt="" /> + </p> + <p>Copy these images for use in this tutorial. Save them into your project +<code>res/drawable/</code> 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 <code>res/drawable/</code> named +<code>ic_tab_artists.xml</code> and insert the following:</p> +<pre> +<?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> +</pre> + <p>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.</p> + + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?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.</p> <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.</p> <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> </pre> - <p>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. </p> - <p>Notice that the TabWidget and the FrameLayout elements have specific <code>android</code> 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.</p> - <p>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.</p> + <p>This is the layout that will display the tabs and provide navigation between each {@link + android.app.Activity} created above.</p> + <p>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.</p> + <p>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.</p> </li> - <li>Now we'll add our code. Open HelloTabWidget.java and make it a <code>TabActivity</code>. - <p>By default, Eclipse creates a class that extends <code>Activity</code>. Change it to - extend <code>TabActivity</code>:</p> - <pre> + + <li>Now open <code>HelloTabWidget.java</code> and make it extend {@link + android.app.TabActivity}:</p> +<pre> public class HelloTabWidget extends TabActivity { -</pre> +</pre> </li> - <li>Now fill in the the <code>onCreate</code> method like this: - <pre> + <li>Use the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} + method: +<pre> 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()); } </pre> - <p>As usual, we start by setting our layout.</p> - <p>We then call the TabActivity method <code>getTabHost()</code>, - which returns us a reference to the TabHost we created in our layout. Upon our TabHost, we call <code>addTab()</code> - 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: - <code>setIndicator()</code> to set the text for the tab button, and <code>setContent()</code> 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.</p> - <p>At the end, we call <code>setCurrentTab()</code> 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 (<var>0</var>).</p> + <p>This sets up each tab with their text and icon, and assigns each one an {@link +android.app.Activity}.</p> + <p>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)}.</p> + + <p>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.</p> + + <p>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}.</p> </li> - <li>To clean-up the presentation a bit more, let's remove the window title that appears at the top of the layout. - Android includes a theme that removes that title for us. To add it, open the Android Manifest file and add - the <var>NoTitleBar</var> theme to the <code><application></code> tag. It should end up like this: - <pre> -<application android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar"> + + <li>Now open the Android Manifest file and add the <code>NoTitleBar</code> theme to the +<em>HelloTabWidget</em>'s + <code><activity></code> 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 <code><activity></code> tag should look like this: +<pre> +<activity android:name=".HelloTabWidget" android:label="@string/app_name" + android:theme="@android:style/Theme.NoTitleBar"> </pre> </li> - <li>That's it. Run your application.</li> + <li>Run the application.</li> </ol> <p>Your application should look like this:</p> <img src="images/hello-tabwidget.png" width="150px" /> -<div class="special"><p>You can include icons in your tabs by passing a -{@link android.graphics.drawable.Drawable} when you call <code>setIndicator()</code>. Here's an example -that uses a Drawable created from an image in the project resources:</p> -<pre>setIndicator("TAB 1", getResources().getDrawable(R.drawable.tab_icon))</pre> -</div> - <h3>References</h3> <ul> <li>{@link android.widget.TabWidget}</li> diff --git a/docs/html/resources/tutorials/views/hello-timepicker.jd b/docs/html/resources/tutorials/views/hello-timepicker.jd index 1a6c8f9..cf16c8e 100644 --- a/docs/html/resources/tutorials/views/hello-timepicker.jd +++ b/docs/html/resources/tutorials/views/hello-timepicker.jd @@ -1,106 +1,97 @@ -page.title=Hello, TimePicker +page.title=Time Picker parent.title=Hello, Views parent.link=index.html @jd:body -<p>A {@link android.widget.TimePicker} is a widget that allows the -user to select the time by hour, minute and AM or PM.</p> +<p>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.</p> +<p>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.</p> <ol> - <li>Start a new project/Activity called HelloTimePicker.</li> - <li>Open the layout file and make it like so: + <li>Start a new project named <em>HelloTimePicker</em>.</li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?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> </pre> - <p>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.</p> - </li> - - <li>Open HelloTimePicker.java. Insert the following to the HelloTimePicker class: -<pre> -private TextView mTimeDisplay; -private Button mPickTime; - -private int mHour; -private int mMinute; - -static final int TIME_DIALOG_ID = 0; +<p>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}.</p> + </li> -@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); - } - }); + <li>Open <code>HelloTimePicker.java</code> and insert the following class members: +<pre> + 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; </pre> -<p class="note"><strong>Tip:</strong> Press Ctrl(or Cmd) + Shift + O to import all needed packages.</p> - <p>We start by instantiating variables for our View elements and time fields. - The <code>TIME_DIALOG_ID</code> is a static integer that uniquely identifies the dialog. In the - <code>onCreate()</code> 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 <code>showDialog()</code> 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 - <code>updateDisplay()</code>—our own method that will fill the TextView with the time.</p> -</li> - -<li>After the <code>onCreate()</code> method, add the <code>onCreateDialog()</code> callback method: +<p>This declares variables for the layout elements and time fields. +The <code>TIME_DIALOG_ID</code> is a static integer that uniquely identifies the dialog.</p> + </li> + <li>Now insert the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} +method: <pre> -@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; -} </pre> - <p>This is passed the identifier we gave <code>showDialog()</code> and initializes - the TimePicker to the time we retrieved from our Calendar instance. It will be called by - <code>showDialog()</code>.</p> + +<p>First, the content is set to the <code>main.xml</code> 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 <code>updateDisplay()</code> method is called in order to fill the {@link +android.widget.TextView} with the current time.</p> </li> -<li>Now add our <code>updateDisplay()</code> method: +<li>Add the <code>updateDisplay()</code> and <code>pad()</code> methods: <pre> // 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); +} </pre> - <p>This simply takes our member fields for the time and inserts them in - the <code>mTimeDisplay</code> TextView. Note that we call a new method, <code>pad()</code>, - on the hour and minute. (We'll create this method in the last step.)</p> +<p>The <code>updateDisplay()</code> method uses the member fields for the time and inserts them in +the <code>mTimeDisplay</code> {@link android.widget.TextView}. The <code>pad()</code> 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.</p> </li> -<li>Next, add a listener to be called when the time is reset: +<li>Add a class member for a {@link android.app.TimePickerDialog.OnTimeSetListener} that will be +called when the user sets a new time: <pre> // the callback received when the user "sets" the time in the dialog private TimePickerDialog.OnTimeSetListener mTimeSetListener = @@ -127,24 +127,31 @@ private TimePickerDialog.OnTimeSetListener mTimeSetListener = } }; </pre> - <p>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.</p> +<p>When the user is done setting the time (clicks the "Set" button), the +<code>onTimeSet()</code> method is called and it updates the member fields with +the new time and updates the layout's {@link android.widget.TextView}.</p> </li> -<li>Finally, add the <code>pad()</code> method that we called from the <code>updateDisplay()</code>: + +<li>Add the {@link android.app.Activity#onCreateDialog(int)} callback method: <pre> -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; } </pre> - <p>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. - </p> +<p>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 <code>onCreate()</code> and the {@link +android.app.TimePickerDialog.OnTimeSetListener} created in the previous step.</p> </li> -<li>Now run it.</li> +<li>Run the application.</li> </ol> <p>When you press the "Change the time" button, you should see the following:</p> <img src="images/hello-timepicker.png" width="150px" /> @@ -152,6 +159,7 @@ private static String pad(int c) { <h3>References</h3> <ol> <li>{@link android.widget.TimePicker}</li> + <li>{@link android.app.TimePickerDialog.OnTimeSetListener}</li> <li>{@link android.widget.Button}</li> <li>{@link android.widget.TextView}</li> <li>{@link java.util.Calendar}</li> diff --git a/docs/html/resources/tutorials/views/hello-webview.jd b/docs/html/resources/tutorials/views/hello-webview.jd index c4388ea..17b2646 100644 --- a/docs/html/resources/tutorials/views/hello-webview.jd +++ b/docs/html/resources/tutorials/views/hello-webview.jd @@ -1,63 +1,72 @@ -page.title=Hello, WebView +page.title=Web View parent.title=Hello, Views parent.link=index.html @jd:body -<p>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.</p> +<p>{@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.</p> <ol> - <li>Create a new project/Activity called HelloWebView.</li> - <li>Open the layout file. Insert a WebView so it looks like so: + <li>Create a new project named <em>HelloWebView</em>.</li> + <li>Open the <code>res/layout/main.xml</code> file and insert the following: <pre> <?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> -</pre></li> +<WebView + android:id="@+id/webview" + android:layout_width="fill_parent" + android:layout_height="fill_parent" +/> +</pre> + </li> - <li>Now open the HelloWebView.java file. - At the top of the class, instantiate a WebView object: -<pre>WebView webview;</pre> - <p> Then add the following at the end of the <code>onCreate()</code> method:</p> + <li>Now open the <code>HelloWebView.java</code> file. + At the top of the class, declare a {@link android.webkit.WebView} object: +<pre>WebView mWebView;</pre> + <p>Then use the following code for the {@link android.app.Activity#onCreate(Bundle) onCreate()} + method:</p> <pre> -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"); +} </pre> - - <p>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.</p></li> - - <li>Because we're accessing the internet, we need to add the appropriate - permissions to the Android manifest file. So open the AndroidManifest.xml file - and, add the following as a child of the <code><manifest></code> element: - - <pre><uses-permission android:name="android.permission.INTERNET" /></pre></li> - - <li>Now run it.</li> -</ol> -<p> 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.</p> - -<hr/> - -<p>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.</p> - -<ol> - <li>In the HelloAndroid Activity, add this nested private class: + <p>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)}.</p> + </li> + + <li>Because this application needs access to the Internet, you need to add the appropriate + permissions to the Android manifest file. Open the <code>AndroidManifest.xml</code> file + and add the following as a child of the <code><manifest></code> element: + + <pre><uses-permission android:name="android.permission.INTERNET" /></pre></li> + + <li>While you're in the manifest, give some more space for web pages by removing the title + bar, with the "NoTitleBar" theme: +<pre> +<activity android:name=".HelloGoogleMaps" android:label="@string/app_name" + <strong>android:theme="@android:style/Theme.NoTitleBar"</strong>> +</pre> + </li> + + <li>Now run the application. + <p>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.</p> + </li> + + <li>In the <code>HelloAndroid</code> Activity, add this nested class: <pre> private class HelloWebViewClient extends WebViewClient { @Override @@ -65,42 +74,51 @@ private class HelloWebViewClient extends WebViewClient { view.loadUrl(url); return true; } -}</pre></li> - - <li>Now, in the <code>onCreate()</code> method, set an instance of the <code>HelloWebViewClient</code> - as our WebViewClient: - <pre>webview.setWebViewClient(new WebViewClientDemo());</pre> - - <p>This line should immediately follow the initialization of our WebView object.</p> - <p>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 <code>shouldOverrideUrlLoading()</code> -method, above—it is passed the current WebView and the URL, so all we do -is load the URL in the given view. Returning <var>true</var> says that we've handled the URL -ourselves and the event should not bubble-up.</p> - <p>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.</p> +} +</pre> + </li> + <li>Then towards the end of the {@link android.app.Activity#onCreate(Bundle)} method, set an + instance of the <code>HelloWebViewClient</code> as the {@link android.webkit.WebViewClient}: + <pre>mWebView.setWebViewClient(new WebViewClientDemo());</pre> + + <p>This line can go anywhere following the initialization of the {@link + android.webkit.WebView} object.</p> + <p>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 <code>true</code> 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).</p> + <p>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.</p> </li> - <li>To handle the back button key press, add the following method inside the HelloWebView -Activity: + <li>To handle the BACK button key press, add the following method inside the + <code>HelloWebView</code> Activity: <pre> @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); -}</pre> - <p>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 - <em>not</em> true, then we send the event up the chain (and the Activity will close). - But if both <em>are</em> true, then we call <code>goBack()</code>, - which will navigate back one step in the history. We then return true to indicate - that we've handled the event.</p> +} +</pre> + <p>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 <code>true</code> indicates that the event has been handled. If this condition + is not met, then the event is sent back to the system.</p> </li> +<li>Run the application again. You'll now be able to follow links and navigate back through the +page history.</li> </ol> <p>When you open the application, it should look like this:</p> <img src="images/hello-webview.png" width="150px" /> @@ -111,8 +129,3 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { <li>{@link android.webkit.WebViewClient}</li> <li>{@link android.view.KeyEvent}</li> </ul> - - - - - diff --git a/docs/html/resources/tutorials/views/images/android_focused.png b/docs/html/resources/tutorials/views/images/android_focused.png Binary files differnew file mode 100644 index 0000000..f84d0fe --- /dev/null +++ b/docs/html/resources/tutorials/views/images/android_focused.png diff --git a/docs/html/resources/tutorials/views/images/android_normal.png b/docs/html/resources/tutorials/views/images/android_normal.png Binary files differnew file mode 100644 index 0000000..94a7084 --- /dev/null +++ b/docs/html/resources/tutorials/views/images/android_normal.png diff --git a/docs/html/resources/tutorials/views/images/android_pressed.png b/docs/html/resources/tutorials/views/images/android_pressed.png Binary files differnew file mode 100644 index 0000000..fe81ff9 --- /dev/null +++ b/docs/html/resources/tutorials/views/images/android_pressed.png diff --git a/docs/html/resources/tutorials/views/images/hello-autocomplete.png b/docs/html/resources/tutorials/views/images/hello-autocomplete.png Binary files differindex e1fd80d..0b3e680 100755..100644 --- a/docs/html/resources/tutorials/views/images/hello-autocomplete.png +++ b/docs/html/resources/tutorials/views/images/hello-autocomplete.png diff --git a/docs/html/resources/tutorials/views/images/hello-formstuff.png b/docs/html/resources/tutorials/views/images/hello-formstuff.png Binary files differindex 3b4bf54..949319f 100755..100644 --- a/docs/html/resources/tutorials/views/images/hello-formstuff.png +++ b/docs/html/resources/tutorials/views/images/hello-formstuff.png diff --git a/docs/html/resources/tutorials/views/images/hello-listview.png b/docs/html/resources/tutorials/views/images/hello-listview.png Binary files differindex a1cf7aa..165b1ac 100755..100644 --- a/docs/html/resources/tutorials/views/images/hello-listview.png +++ b/docs/html/resources/tutorials/views/images/hello-listview.png diff --git a/docs/html/resources/tutorials/views/images/hello-mapview.png b/docs/html/resources/tutorials/views/images/hello-mapview.png Binary files differindex 0956760..6bd9740 100755..100644 --- a/docs/html/resources/tutorials/views/images/hello-mapview.png +++ b/docs/html/resources/tutorials/views/images/hello-mapview.png diff --git a/docs/html/resources/tutorials/views/images/hello-tabwidget.png b/docs/html/resources/tutorials/views/images/hello-tabwidget.png Binary files differindex 6a52356..6580c5b 100644 --- a/docs/html/resources/tutorials/views/images/hello-tabwidget.png +++ b/docs/html/resources/tutorials/views/images/hello-tabwidget.png diff --git a/docs/html/resources/tutorials/views/images/hello-webview.png b/docs/html/resources/tutorials/views/images/hello-webview.png Binary files differindex 283ce7d..248c6d4 100755..100644 --- a/docs/html/resources/tutorials/views/images/hello-webview.png +++ b/docs/html/resources/tutorials/views/images/hello-webview.png diff --git a/docs/html/resources/tutorials/views/images/ic_tab_artists_grey.png b/docs/html/resources/tutorials/views/images/ic_tab_artists_grey.png Binary files differnew file mode 100644 index 0000000..9baa30e --- /dev/null +++ b/docs/html/resources/tutorials/views/images/ic_tab_artists_grey.png diff --git a/docs/html/resources/tutorials/views/images/ic_tab_artists_white.png b/docs/html/resources/tutorials/views/images/ic_tab_artists_white.png Binary files differnew file mode 100644 index 0000000..3b010d5 --- /dev/null +++ b/docs/html/resources/tutorials/views/images/ic_tab_artists_white.png diff --git a/docs/html/resources/tutorials/views/index.jd b/docs/html/resources/tutorials/views/index.jd index 2cb5d3a..6ea7683 100644 --- a/docs/html/resources/tutorials/views/index.jd +++ b/docs/html/resources/tutorials/views/index.jd @@ -3,116 +3,117 @@ page.title=Hello, Views <style> .view {float:left; margin:10px; font-size:120%; font-weight:bold;} -.view img {border:1px solid black; margin:5px 0 0; padding:5px;} +#jd-content .view img {border:1px solid black; margin:8px 0 0 0; padding:5px;} </style> -<p>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.</p> +<p>This is a collection of "Hello World"-style tutorials designed +to get you started quickly with common Android layouts and widgets.</p> -<p>Note that a certain amount of knowledge is assumed for these tutorials. If you haven't -completed the <a href="{@docRoot}resources/tutorials/hello-world.html">Hello, World</a> 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:</p> +<p>A certain amount of knowledge is assumed for these tutorials. Before you start, +you should have completed the <a href="{@docRoot}resources/tutorials/hello-world.html">Hello, +World</a> tutorial—it will teach you several things about basic +Android development. More specifically, you should know:</p> <ul> - <li>How to create a new Android project.</li> - <li>The basic structure of an Android project (resource files, layout files, etc.).</li> - <li>The essential components of an {@link android.app.Activity}.</li> - <li>How to build and run a project.</li> + <li>How to create an Android project and run it</li> + <li>The basic structure of an Android project (resource files, layout files, etc.)</li> + <li>The basic components of an {@link android.app.Activity}</li> </ul> -<p>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.</p> -<p>With this knowledge, you're ready to begin, so take your pick.</p> -<div> +<p class="note"><strong>Note:</strong> 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 +<code>res/values/strings.xml</code> resource file.</p> + +<p class="note"><strong>Tip:</strong> After you have pasted sample code into an Eclipse project, +press <strong>Ctrl (or Cmd) + Shift + O</strong> to import the required packages.</p> + +<h2>Layouts</h2> <div class="view"> -<a href="hello-linearlayout.html">LinearLayout</a><br/> -<a href="hello-linearlayout.html"><img src="images/hello-linearlayout.png" height="285" width="200" /></a> +<a href="hello-linearlayout.html">Linear Layout</a><br/> +<a href="hello-linearlayout.html"><img src="images/hello-linearlayout.png" height="285" width="200" +/></a> </div> + <div class="view"> -<a href="hello-relativelayout.html">RelativeLayout</a><br/> -<a href="hello-relativelayout.html"><img src="images/hello-relativelayout.png" height="285" width="200" /></a> +<a href="hello-relativelayout.html">Relative Layout</a><br/> +<a href="hello-relativelayout.html"><img src="images/hello-relativelayout.png" height="285" +width="200" /></a> </div> + <div class="view"> -<a href="hello-tablelayout.html">TableLayout</a><br/> -<a href="hello-tablelayout.html"><img src="images/hello-tablelayout.png" height="285" width="200" /></a> +<a href="hello-tablelayout.html">Table Layout</a><br/> +<a href="hello-tablelayout.html"><img src="images/hello-tablelayout.png" height="285" width="200" +/></a> </div> <div class="view"> -<a href="hello-datepicker.html">DatePicker</a><br/> -<a href="hello-datepicker.html"><img src="images/hello-datepicker.png" height="285" width="200" /></a> +<a href="hello-gridview.html">Grid View</a><br/> +<a href="hello-gridview.html"><img src="images/hello-gridview.png" height="285" width="200" /></a> </div> <div class="view"> -<a href="hello-timepicker.html">TimePicker</a><br/> -<a href="hello-timepicker.html"><img src="images/hello-timepicker.png" height="285" width="200" /></a> +<a href="hello-tabwidget.html">Tab Layout</a><br/> +<a href="hello-tabwidget.html"><img src="images/hello-tabwidget.png" height="285" width="200" /></a> </div> + <div class="view"> -<a href="hello-formstuff.html">Form Stuff</a><br/> -<a href="hello-formstuff.html"><img src="images/hello-formstuff.png" height="285" width="200" /></a> +<a href="hello-listview.html">List View</a><br/> +<a href="hello-listview.html"><img src="images/hello-listview.png" height="285" width="200" /></a> </div> + +<p style="clear:left"> </p> + +<h2>Widgets & Other Views</h2> + <div class="view"> -<a href="hello-spinner.html">Spinner</a><br/> -<a href="hello-spinner.html"><img src="images/hello-spinner.png" height="285" width="200" /></a> +<a href="hello-datepicker.html">Date Picker</a><br/> +<a href="hello-datepicker.html"><img src="images/hello-datepicker.png" height="285" width="200" +/></a> </div> <div class="view"> -<a href="hello-autocomplete.html">AutoComplete</a><br/> -<a href="hello-autocomplete.html"><img src="images/hello-autocomplete.png" height="285" width="200" /></a> +<a href="hello-timepicker.html">Time Picker</a><br/> +<a href="hello-timepicker.html"><img src="images/hello-timepicker.png" height="285" width="200" +/></a> </div> + <div class="view"> -<a href="hello-listview.html">ListView</a><br/> -<a href="hello-listview.html"><img src="images/hello-listview.png" height="285" width="200" /></a> +<a href="hello-formstuff.html">Form Stuff</a><br/> +<a href="hello-formstuff.html"><img src="images/hello-formstuff.png" height="285" width="200" /></a> </div> + <div class="view"> -<a href="hello-gridview.html">GridView</a><br/> -<a href="hello-gridview.html"><img src="images/hello-gridview.png" height="285" width="200" /></a> +<a href="hello-spinner.html">Spinner</a><br/> +<a href="hello-spinner.html"><img src="images/hello-spinner.png" height="285" width="200" /></a> </div> <div class="view"> -<a href="hello-gallery.html">Gallery</a><br/> -<a href="hello-gallery.html"><img src="images/hello-gallery.png" height="285" width="200" /></a> +<a href="hello-autocomplete.html">Auto Complete</a><br/> +<a href="hello-autocomplete.html"><img src="images/hello-autocomplete.png" height="285" width="200" +/></a> </div> <div class="view"> -<a href="hello-tabwidget.html">TabWidget</a><br/> -<a href="hello-tabwidget.html"><img src="images/hello-tabwidget.png" height="285" width="200" /></a> +<a href="hello-gallery.html">Gallery</a><br/> +<a href="hello-gallery.html"><img src="images/hello-gallery.png" height="285" width="200" /></a> </div> <div class="view"> -<a href="hello-mapview.html">MapView</a><br/> +<a href="hello-mapview.html">Google Map View</a><br/> <a href="hello-mapview.html"><img src="images/hello-mapview.png" height="285" width="200" /></a> </div> <div class="view"> -<a href="hello-webview.html">WebView</a><br/> +<a href="hello-webview.html">Web View</a><br/> <a href="hello-webview.html"><img src="images/hello-webview.png" height="285" width="200" /></a> </div> -<!-- -TODO - -<div class="view"> -<a href="hello-popupwindow.html">PopupWindow<br/> -<img src="images/hello-popupwindow.png" height="285" width="200" /></a> -</div> -<div class="view"> -<a href="hello-tabhost.html">TabHost / TabWidget<br/> -<img src="images/hello-tabhost.png" height="285" width="200" /></a> -</div> -ProgressBar; RatingBar; FrameLayout - ---> <p class="note" style="clear:left"> -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 -<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/index.html">Api Demos</a>. -These can also be found offline, in <code>/<sdk>/samples/ApiDemos</code>.</p> -</div> +<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/index.html">Api +Demos</a>.</p> diff --git a/docs/html/shareables/sample_images.zip b/docs/html/shareables/sample_images.zip Binary files differnew file mode 100644 index 0000000..007a68a --- /dev/null +++ b/docs/html/shareables/sample_images.zip |