Chapter 9

Employing Basic Widgets

Every GUI toolkit has some basic widgets: fields, labels, buttons, and so forth. Android's toolkit is no different in scope, and the basic widgets provide a good introduction to how widgets work in Android activities.

Assigning Labels

The simplest widgets the label, referred to in Android as a TextView. As in most GUI toolkits, labels are bits of text that can't be edited directly by users. Typically, labels are used to identify adjacent widgets (e.g., a “Name:” label next to a field where the user fills in a name

In Java, you can create a label by creating a TextView instance. More commonly, though, you will create labels in XML layout files by adding a TextView element to the layout, with an android:text property to set the value of the label itself. If you need to swap labels based on certain criteria, such as internationalization, you may wish to use a string resource reference in the XML instead, as will be described later in this book.

TextView has numerous other properties of relevance for labels, such as the following

  • android:typeface: Sets the typeface to use for the label (e.g., monospace)
  • android:textStyle: Indicates that the typeface should be made bold (bold), italic (italic), or bold and italic (bold_italic)
  • android:textSize: Specifies the size of the font, in one of several measures: sp (scaled pixels), dip (density-independent pixels), px (raw pixels), in (inches), mm (millimeters). The recommend approach is to use sp, and this is appended to the size, such as 12sp.
  • android:textColor: Sets the color of the label's text, in RGB hex format (e.g., #FF0000 for red)

For example, in the Basic/Label project, you will find the following layout file:

<?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="wrap_content"
  android:text="You were expecting something profound?"
  />

Just that layout alone, with the stub Java source provided by Android's project builder (e.g., android create project), gives you the result shown in Figure 9–1.

images

Figure 9–1. The LabelDemo sample application

In our XML responsible for the LabelDemo, you'll note we used two width and height directives. The first, fill_parent, indicates we want our UI element to completely fill its parent space, minus any padding or border. The second, wrap_content, ensures that only enough space within the parent to show our content is used, and no more. These will become clearer as we step through more examples in the coming chapters.

Button, Button, Who's Got the Button?

You've already seen the use of the Button widget the previous two chapters. As it turns out, Button is a subclass of TextView, so everything discussed in the preceding section also applies to formatting the face of the button.

Android offers you two approaches when you are dealing with the on-click listener for a Button. The first option is the “classic” way of defining some object (such as the activity) as implementing the View.OnClickListener interface. Even better than the classic method is the contemporary Android way of simplifying things. This simple option has two steps:

  1. Define some method on your Activity that holds the button that takes a single View parameter, has a void return value, and is public.
  2. In your layout XML, on the Button element, include the android:onClick attribute with the name of the method you defined in the previous step.

For example, we might have a method on our Activity that looks like this:

public void someMethod(View theButton) {
 // do something useful here
}

Then, we could use this XML declaration for the Button itself, including android:onClick:

<Button
 android:onClick="someMethod"
 ...
/>

This is enough for Android to wire together the Button with the click handler. At first you may not feel this is any simpler than the traditional approach. But consider the ease with which this method opens up options to change the Activity for a given Button through simple dint of differing options in your XML specification—for instance, under different language locales, screen sizes, and so forth. We will talk more about these options in coming chapters.

Fleeting Images

Android has two widgets to help you embed images in your activities: ImageView and ImageButton. As the names suggest, they are image-based analogues to TextView and Button, respectively.

Each widget takes an android:src attribute (in an XML layout) to specify which picture to use. These attributes usually reference a drawable resource, described in greater detail in Chapter 23, which discusses resources.

ImageButton, a subclass of ImageView, mixes in the standard Button behaviors, for responding to clicks and whatnot. For example, take a peek at the main.xml layout from the Basic/ImageView sample project:

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/icon"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:adjustViewBounds="true"
    android:src="@drawable/molecule"
    />

The result, just using the code-generated activity, is simply the image, as shown in Figure 9–2.

images

Figure 9–2. The ImageViewDemo sample application

Fields of Green…or Other Colors

Along with buttons and labels, fields are the third anchor of most GUI toolkits. In Android, they are implemented via the EditText widget, which is a subclass of the TextView used for labels.

Along with the standard TextView properties (e.g., android:textStyle), EditText has many other properties that will be useful to you in constructing fields, including the following:

  • android:autoText: Controls if the field should provide automatic spelling assistance
  • android:capitalize: Controls if the field should automatically capitalize the first letter of entered text (e.g., in name and city fields)
  • android:digits: Configures the field to accept only certain digits
  • android:password: Configures the field to display password dots as characters are typed into the field, hiding the typed characters
  • android:singleLine: Controls if the field is for single-line input or multiple-line input (e.g., does pressing Enter move you to the next widget or add a newline?)

Most of the preceding properties are also available from the new android:inputType attribute, added in Android 1.5 as part of adding “soft keyboards” to Android (discussed in Chapter 11).

For example, from the Basic/Field project, here is an XML layout file showing an EditText widget:

<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/field"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:singleLine="false"
  />

Note that android:singleLine is set to "false", so users will be able to enter several lines of text.

For this project, the FieldDemo.java file populates the input field with some prose:

package com.commonsware.android.field;

import android.app.Activity;
import android.os.Bundle;
import android.widget.EditText;

public class FieldDemo extends Activity {
  @Override
  public void onCreate(Bundle icicle) {
      super.onCreate(icicle);
      setContentView(R.layout.main);

      EditText fld=(EditText)findViewById(R.id.field);
      fld.setText("Licensed under the Apache License, Version 2.0 " +
              "(the "License"); you may not use this file " +
              "except in compliance with the License. You may " +
              "obtain a copy of the License at " +
              "http://www.apache.org/licenses/LICENSE-2.0");
  }
}

The result, once built and installed into the emulator, is shown in Figure 9–3.

Another flavor of field is one that offers autocompletion, to help users supply a value without typing in the whole text. That is provided in Android as the AutoCompleteTextView widget, discussed in greater detail in Chapter 12.

images

Figure 9–3. The FieldDemo sample application

Just Another Box to Check

The classic check box has two states: checked and unchecked. Clicking the check box toggles between those states to indicate a choice (e.g., “Add rush delivery to my order”).

In Android, there is a CheckBox widget to meet this need. It has TextView as an ancestor, so you can use TextView properties like android:textColor to format the widget.

Within Java, you can invoke the following:

  • isChecked(): Determines if the check box has been checked
  • setChecked(): Forces the check box into a checked or unchecked state
  • toggle(): Toggles the check box as if the user checked it

Also, you can register a listener object (in this case, an instance of OnCheckedChangeListener) to be notified when the state of the check box changes.

For example, from the Basic/CheckBox project, here is a simple check box layout:

<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/check"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="This checkbox is: unchecked" />

The corresponding CheckBoxDemo.java retrieves and configures the behavior of the check box:

public class CheckBoxDemo extends Activity
  implements CompoundButton.OnCheckedChangeListener {
  CheckBox cb;

  @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.main);

    cb=(CheckBox)findViewById(R.id.check);
    cb.setOnCheckedChangeListener(this);
  }

  public void onCheckedChanged(CompoundButton buttonView,
                                 boolean isChecked) {
      if (isChecked) {
        cb.setText("This checkbox is: checked");
      }
      else {
        cb.setText("This checkbox is: unchecked");
    }
  }
}

Note that the activity serves as its own listener for check box state changes, since it implements the OnCheckedChangeListener interface (via cb.setOnCheckedChangeListener(this)). The callback for the listener is onCheckedChanged(), which receives the check box whose state has changed and the new state. In this case, we update the text of the check box to reflect what the actual box contains.

The result? Clicking the check box immediately updates its text, as shown in Figures 9–4 and 9–5.

images

Figure 9–4. The CheckBoxDemo sample application, with the check box unchecked

images

Figure 9–5. The same application, now with the check box checked

Throw the Switch, Igor

New to Android 4.0 (Ice Cream Sandwich) is a variant of the CheckBox. This is a two-state toggle Switch that enables the user to swipe or drag with their finger as if they were toggling a light switch. They can also tap the Switch widget as if it were a CheckBox to change its state.

The Switch provides an android:text property to display associated text with the Switch state, which is controlled via the setTextOn() and setTextOff() methods of the Switch.

Other useful methods available for a Switch include:

  • getTextOn(): Returns the text used when the Switch is on
  • getTextOff(): Returns the text used when the Switch is off
  • setChecked(): Changes the current Switch state to on (just like CheckBox)

For example, from the Basic/Switch project, here is a simple Switch layout:

<?xml version="1.0" encoding="utf-8"?>
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/switchdemo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="This switch is: off" />

Note that we couldn't call the widget “switch” because of reserved-word conventions in Java. The corresponding SwitchActivity.java retrieves and configures the behavior of the switch We once again configure our class to implement the OnCheckChangedListener interface, and it takes care of calling our onCheckedChanged method:

public class SwitchDemo extends Activity
  implements CompoundButton.OnCheckedChangeListener {
  Switch sw;

  @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.main);

    sw=(Switch)findViewById(R.id.switchdemo);
    sw.setOnCheckedChangeListener(this);
  }

  public void onCheckedChanged(CompoundButton buttonView,
                                 boolean isChecked) {
    if (isChecked) {
      sw.setTextOn("This switch is: on");
    }
    else {
      sw.setTextOff("This switch is: off");
    }
  }
}

You can see from the general structure, use of parent methods, and behavior that the Switch operates in very similar ways to the CheckBox. Our results are shown in Figures 9–6 and 9–7 with the switch in each possible state.

images

Figure 9–6. The SwitchDemo sample application, with the switch off

images

Figure 9–7. The same application, now with the switch on

Turn Up the Radio

As with other implementations of radio buttons in other toolkits, Android's radio buttons are two-state, like check boxes and switches, but can be grouped such that only one radio button in the group can be checked at any time.

Like CheckBox, RadioButton inherits from CompoundButton, which in turn inherits from TextView. Hence, all the standard TextView properties for font face, style, color, and so forth are available for controlling the look of radio buttons. Similarly, you can call isChecked() on a RadioButton to see if it is selected, toggle() to select it, and so on, as you can with a CheckBox.

Most times, you will want to put your RadioButton widgets inside a RadioGroup. The RadioGroup indicates a set of radio buttons whose state is tied, meaning only one button in the group can be selected at any time. If you assign an android:id to your RadioGroup in your XML layout, you can access the group from your Java code and invoke the following:

  • check(): Checks a specific radio button via its ID (e.g., group.check(R.id.radio1))
  • clearCheck(): Clears all radio buttons, so none in the group is checked
  • getCheckedRadioButtonId(): Gets the ID of the currently checked radio button (or -1 if none is checked)

Note that the mutual-exclusion feature of RadioGroup applies only to RadioButton widgets that are immediate children of the RadioGroup. You cannot have other containers—discussed in the next chapter—between the RadioGroup and its RadioButton widgets.

For example, from the Basic/RadioButton sample application, here is an XML layout showing a RadioGroup wrapping a set of RadioButton widgets:

<?xml version="1.0" encoding="utf-8"?>
<RadioGroup
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  >
    <RadioButton android:id="@+id/radio1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Rock" />

    <RadioButton android:id="@+id/radio2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Scissors" />

    <RadioButton android:id="@+id/radio3"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Paper" />
</RadioGroup>

Using the stock Android-generated Java for the project and this layout, you get the result shown in Figure 9–8.

Note that the radio button group is initially set to be completely unchecked at the outset. To preset one of the radio buttons to be checked, use either setChecked() on the RadioButton or check() on the RadioGroup from within your onCreate() callback in your activity.

images

Figure 9–8. The RadioButtonDemo sample application

It's Quite a View

All widgets, including the ones shown in the previous sections, extend View, which gives all widgets an array of useful properties and methods beyond those already described.

Padding

Widgets have a minimum size, which may be influenced by what is inside of them. So, for example, a Button will expand to accommodate the size of its caption. You can control this size by using padding. Adding padding will increase the space between the contents (e.g., the caption of a Button) and the edges of the widget.

Padding can be set once in XML for all four sides (android:padding) or on a per-side basis (android:paddingLeft, etc.). Padding can also be set in Java via the setPadding() method.

The value of any of these is a dimension, a combination of a unit of measure and a count. So, 5px is 5 pixels, 10dip is 10 density-independent pixels, and 2mm is 2 millimeters. We will examine dimension in greater detail in Chapter 25.

Other Useful Properties

In addition to the properties presented in this chapter and in the next chapter, some of the other properties of View that are most likely to be used include the following:

  • android:visibility: Controls whether the widget is initially visible
  • android:nextFocusDown, android:nextFocusLeft, android:nextFocusRight, and android:nextFocusUp: Control the focus order if the user uses the D-pad, trackball, or similar pointing device
  • android:contentDescription: Roughly equivalent to the alt attribute on an HTML <img> tag, used by accessibility tools to help people who cannot see the screen navigate the application

Useful Methods

You can toggle whether or not a widget is enabled via setEnabled() and see whether or not it is enabled via isEnabled(). One common use pattern for this is to disable some widgets based on a CheckBox or RadioButton selection.

You can give a widget focus via requestFocus() and see if it is focused via isFocused(). You might use this in concert with disabling widgets to ensure the proper widget has the focus once your disabling operation is complete.

To help navigate the tree of widgets and containers that make up an activity's overall view, you can use:

  • getParent(): Finds the parent widget or container
  • findViewById(): Finds a child widget with a certain ID
  • getRootView(): Gets the root of the tree (e.g., what you provided to the activity via setContentView())

Colors

There are two types of color attributes in Android widgets. Some, like android:background, take a single color (or a graphic image to serve as the background). Others, like android:textColor on TextView (and subclasses), can take a ColorStateList, including via the Java setter (in this case, setTextColor()).

A ColorStateList allows you to specify different colors for different conditions. For example, a TextView can have one text color when it is the selected item in a list and another color when it is not selected (Chapter 12 covers selection widgets). This is handled via the default ColorStateList associated with TextView.

If you wish to change the color of a TextView widget in Java code, you have two main choices:

  • Use ColorStateList.valueOf(), which returns a ColorStateList in which all states are considered to have the same color, which you supply as the parameter to the valueOf() method. This is the Java equivalent of the android:textColor approach, to make the TextView always a specific color regardless of circumstances.
  • Create a ColorStateList with different values for different states, either via the constructor or via an XML drawable resource, a concept discussed in Chapter 23.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset