Previous section   Next section

Mobile Phone Handheld Hardware Hardware Rick Rogers John Lombardo O'Reilly Media, Inc. O'Reilly Media Android Application Development, 1st Edition

11.1. Android Views

The Views in the following section are the meat and potatoes of your application; essential widgets that you'll use over and over and that your users will be familiar with from other applications.

11.1.1. TextView and EditText

A TextView, as shown in the line "This is some text" in Figure 11-1, is just what you'd expect: a place to display a text string. The vanilla TextView is for display only, whereas EditText is a predefined subclass of TextView that includes rich editing capabilities.

Figure 11-1. TextView, EditText, and Button


Each TextView has the attributes you'd expect of such a component: you can change its height, width, font, text color, background color, and so forth. TextViews also have some useful unique attributes:


autoLink

If set (true), finds URLs in the displayed text and automatically converts them to clickable links.


autoText

If set (true), finds and corrects simple spelling errors in the text.


editable

If set (true), indicates that the program has defined an input method to receive input text (default is false for TextView, and true for EditText).


inputMethod

Identifies the input method (EditText defines one for generic text).

Example 11-1 shows how to use a TextView and an EditText with Buttons. (Buttons are covered in the next section.) It also shows the XML layout file (main.xml), which uses pretty standard and recommended layout parameters.

Example 11-1. Layout file for TextView and EditView example

<?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"
   >
<TextView
    android:id="@+id/txtDemo"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />
<EditText
    android:id="@+id/eTxtDemo"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />
<Button
    android:id="@+id/btnDone"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Log it"
    />
</LinearLayout>

Example 11-2 contains the accompanying Java source (TextViewDemo.java).

Example 11-2. Java for TextView and EditView: TextViewDemo.java

package com.oreilly.demo;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class TextViewDemo extends Activity {
    private static TextView txt1;
    private static EditText etxt1;
    private static Button btn1;

    // Create a button click listener for the Done button.
    private final Button.OnClickListener btnDoneOnClick = new Button.OnClickListener() {
        public void onClick(View v) {
          String input = etxt1.getText().toString();
          //Log the input string
          Log.v("TextViewDemo", input);
          etxt1.setText("");
        }
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //Get pointers to the Views defined in main.xml
        txt1 = (TextView) findViewById(R.id.txtDemo);
        etxt1 = (EditText) findViewById(R.id.eTxtDemo);
        btn1 = (Button) findViewById(R.id.btnDone);

        //Set the string displayed in TextView1
        txt1.setText("This is some text.");

        //Set the OnClickListener for the Done button
        btn1.setOnClickListener(btnDoneOnClick);
    }
}

Here are some of the highlights of the code:

Now the user can enter and edit text in the EditText, and when he clicks on "Log it", the OnClickListener is called and the text is written to the logcat log. The string in the EditText is cleared out, and the widget is ready for another entry.

11.1.2. Button and ImageButton

The Button View is just a button, printed with some text to identify it, that the user can click to invoke some action. The previous section created a Button and connected it to an OnClickListener method that executes when the Button is clicked.

Android has a very visual, mobile-oriented user interface, so you might want to use a button with an image on it rather than one with text. Android provides the ImageButton View for just that purpose. You can adapt Example 11-2 to use an ImageButton by making one change in the XML file and another in the Java code:

  1. In main.xml, replace the Button definition for btnDone with an ImageButton:

    ...
    <ImageButton
      android:id="@+id/btnDone"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      />
    ...
  2. In TextViewDemo.java, redefine btn1 as an ImageButton and add a line to set the image to a PNG image in the drawable directory:

    ...
        private static ImageButton btn1;
    
    ...
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            //Get pointers to the Views defined in main.xml
            txt1 = (TextView) findViewById(R.id.txtDemo);
            etxt1 = (EditText) findViewById(R.id.eTxtDemo);
            btn1 = (ImageButton) findViewById(R.id.btnDone);
    ...
            //Set the image for the Done button
            btn1.setImageResource(R.drawable.log);
    ...

The button now appears as shown in Figure 11-2.

Figure 11-2. Text boxes with an ImageButton


11.1.3. Adapters and AdapterViews

Adapters and AdapterViews are an important and useful basis for several of the views discussed in the rest of this chapter. Using extensions to these classes, you can address an extremely wide variety of situations.

The AdapterView is a generic, list-oriented view of data. Any collection of data objects that can be ordered in some relatively stable way can be displayed through an AdapterView. An AdapterView is always associated with an Adapter, which acts as the bridge between it and the underlying data collection. The Adapter has two responsibilities:

  • At the request of the AdapterView, the Adapter must be able to find the data object that corresponds to a particular index. It must, in other words, be able to find the data object that is visible in the AdapterView at a particular location.

  • Inversely, the Adapter must be able to supply a view through which the data at a particular index can be displayed.

It takes only a moment's reflection to understand how the AdapterView works: It is a ViewGroup that contains all the machinery necessary to serve as both the View and Controller for a collection of generic widgets. It can lay them out on the display, pass in clicks and keystrokes, and so on. It need never concern itself with what the subviews actually display; it distinguishes them only by their indexes. Whenever it needs to perform either of the two operations that are not entirely generic—creating a new view or getting the data object attached to a particular view—it relies on the Adapter to convert an index into either a data object or the view of a data object.

The AdapterView requests new views from an implementation of the Adapter interface, as it needs them, for display. For instance, as a user scrolls though a list of contacts, the AdapterView requests a new view for each new contact that becomes visible. As an optimization, the AdapterView may offer a view that is no longer visible (in this case, one that has scrolled off the display) for reuse. This can dramatically reduce memory churn and speed up display.

When offered a recycled view, however, the Adapter must verify that it is the right kind of view through which to display the data object at the requested index. This is necessary because the Adapter is not limited to returning instances of a single view class in response to the request for a view. If the Adapter represents several kinds of objects, it might create several different types of views, each applicable to some subset of the data objects in the collection. A list of contacts, for instance, might have two entirely different view classes: one for displaying acquaintances that are currently online and another for those who are not. The latter might completely ignore clicks, whereas the former would open a new chat session when clicked.

Although AdapterView and Adapter are both abstract and cannot be directly instantiated, the UI toolkit includes several prebuilt Adapters and AdapterViews that can be used unmodified or further subclassed to provide your own customizations. ListAdapter and SpinnerAdapter are particularly useful Adapters, while ListView, GridView, Spinner, and Gallery are all handy subclasses of AdapterView. If you plan to create your own subclass of AdapterView, a quick look at the code for one of these classes will get you off to a running start.

A good example of the use of an AdapterView can be found in Section 11.2.1. The Gallery view in that section is a subclass of AdapterView, and uses a subclass of Adapter called ImageAdapter.

11.1.4. CheckBoxes, RadioButtons, and Spinners

The Views we present in this section are probably familiar to you from other user interfaces. Their purpose is to allow the user to choose from multiple options. CheckBoxes are typically used when you want to offer multiple selections with a yes/no or true/false choice for each. RadioButtons are used when only one choice is allowed at a time.

Spinners are similar to combo boxes in some frameworks. A combo box typically displays the currently selected option, along with a pull-down list from which the user can click on another option to select it.

Android has adapted these familiar components to make them more useful in a touchscreen environment. Figure 11-3 shows the three types of multiple-choice Views laid out on an Android application, with the Spinner pulled down to show the options.

Figure 11-3. CheckBox, RadioButtons, and Spinner


The layout XML file that created the screen in the figure looks like this:

<?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"
    >
<CheckBox
  android:id="@+id/cbxBox1"
  android:layout_width="20dp"
  android:layout_height="20dp"
  android:checked="false"
  />
<TextView
  android:id="@+id/txtCheckBox"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="CheckBox: Not checked"
    />
<RadioGroup
  android:id="@+id/rgGroup1"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical">
  <RadioButton android:id="@+id/RB1" android:text="Button1" />
  <RadioButton android:id="@+id/RB2" android:text="Button2" />
  <RadioButton android:id="@+id/RB3" android:text="Button3" />
  </RadioGroup>
<TextView
  android:id="@+id/txtRadio"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="RadioGroup: Nothing picked"
  />
<Spinner
  android:id="@+id/spnMusketeers"
  android:layout_width="250dp"
  android:layout_height="wrap_content"
  android:layout_centerHorizontal="true"
  android:layout_marginTop="2dp"
  />
</LinearLayout>

The file just lists each View we want on the screen along with the attributes we want. A RadioGroup is really a ViewGroup, so it contains the appropriate RadioButton Views. Example 11-3 shows the Java file that responds to user clicks.

Example 11-3. Java for CheckBox, RadioButtons, and Spinner

package com.oreilly.select;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.google.android.maps.GeoPoint;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener;

public class SelectExample extends Activity {

  private CheckBox checkBox;
  private TextView txtCheckBox, txtRadio;
  private RadioButton rb1, rb2, rb3;
  private Spinner spnMusketeers;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        checkBox = (CheckBox) findViewById(R.id.cbxBox1);
        txtCheckBox = (TextView) findViewById(R.id.txtCheckBox);
        txtRadio = (TextView) findViewById(R.id.txtRadio);
        rb1 = (RadioButton) findViewById(R.id.RB1);
        rb2 = (RadioButton) findViewById(R.id.RB2);
        rb3 = (RadioButton) findViewById(R.id.RB3);
        spnMusketeers = (Spinner) findViewById(R.id.spnMusketeers);

        // React to events from the CheckBox
        checkBox.setOnClickListener(new CheckBox.OnClickListener() {
          public void onClick(View v){
                if (checkBox.isChecked()) {
                    txtCheckBox.setText("CheckBox: Box is checked");
                }
                else
                {
                  txtCheckBox.setText("CheckBox: Not checked");
                }
          }
        });

        // React to events from the RadioGroup
        rb1.setOnClickListener(new RadioGroup.OnClickListener() {
          public void onClick(View v){
            txtRadio.setText("Radio: Button 1 picked");
          }
        });

        rb2.setOnClickListener(new RadioGroup.OnClickListener() {
          public void onClick(View v){
            txtRadio.setText("Radio: Button 2 picked");
          }
        });

        rb3.setOnClickListener(new RadioGroup.OnClickListener() {
          public void onClick(View v){
            txtRadio.setText("Radio: Button 3 picked");
          }
        });

        // Set up the Spinner entries
        List<String> lsMusketeers = new ArrayList<String>();
        lsMusketeers.add("Athos");
        lsMusketeers.add("Porthos");
        lsMusketeers.add("Aramis");

        ArrayAdapter<String> aspnMusketeers = 
          new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, 
           lsMusketeers);
        aspnMusketeers.setDropDownViewResource
           (android.R.layout.simple_spinner_dropdown_item);
        spnMusketeers.setAdapter(aspnMusketeers);

    // Set up a callback for the spinner
    spnMusketeers.setOnItemSelectedListener(
        new OnItemSelectedListener() {
            public void onNothingSelected(AdapterView<?> arg0) { }

            public void onItemSelected(AdapterView<?> parent, View v, 
             int position, long id)  {

              // Code that does something when the Spinner value changes
            }
        });
    }
}

The Views work as follows:


CheckBox

The CheckBox View takes care of flipping its state back and forth and displaying the appropriate checkmark when the state is true. All you have to do is create an "OnClickListener" to catch click events, and you can add whatever code you want to react.


RadioGroup

As mentioned earlier, the RadioGroup View is really a ViewGroup that contains any number of RadioButton Views. The user can select only one of the buttons at a time, and you capture the selections by setting OnClickListeners for each RadioButton. Note that clicking on one of the RadioButtons does not fire a click event for the RadioGroup.


Spinner

Spinners require the most work of these three Views, but can also provide the best use of scarce screen real estate. As shown, the Spinner is normally collapsed to the currently selected entry, and when you touch the down arrow on the right, it presents a drop-down list of the other choices. To make that happen, you must:

  1. Create a list of the selections (which can be a dynamic list built and changed by your application).

  2. Create an ArrayAdapter from the list that the Spinner can use for its drop-down list. Note that the formats shown for the ArrayAdapter (simple_spinner_item and simple_spinner_dropdown_item) are defined by Android; they do not appear in your resource XML files.

  3. Create an onItemSelectedListener for the Spinner to capture select events. The listener has to contain both an onItemSelected method and an onNothingSelected method.

          
      Previous section   Next section
     


    Women's attire - beach wedding dresses.