Chapter 6

Improving Your App

In This Chapter

check1 Improving the look of an app

check1 Helping people in other countries use your app

check1 Getting your app to communicate with the outside world

Face it — the app in Chapter 5 of this minibook is boring! Really boring! Who wants to click a button to see the words Pepperoni Extra Cheese on a device’s screen?

In this chapter, you improve on the app that you created in Chapter 5. I can’t promise instant excitement, but with modest effort, you can add features to make the app more interesting. (I confess: In this chapter, the real reason for making the app interesting is to show you some additional Android developer tricks. Anyway, read on …)

Improving the Layout

In addition to being boring, the app in Chapter 5 is ugly. You can improve an app’s look in two ways — the way it looks to a user and the way it looks to another developer. In this section, you do both. When you’re done, you have a layout like the one in Figure 6-1.

image

Figure 6-1: Your mission, should you decide to accept it.

Before creating the layout’s code, I want to make some observations about the layout in Figure 6-1:

  • The button is below the pair of check boxes.
  • The check boxes are side-by-side.
  • The pair of check boxes is centered (side by side) on the screen.
  • The button is centered on the screen.
  • Taken as a group, the check boxes and the button don’t fill the entire screen.

You may wonder why I make these five observations and not others. If so, read on.

  1. Launch Android Studio and create a new Android project.

    For details on creating a new project, see Chapter 3 of this minibook.

  2. In the Designer tool’s preview screen, select the Hello World! text view.

    It’s time to get rid of this silly text view.

  3. Press Delete.

    Goodbye world!

    You want something that aligns objects vertically so that the button is below the pair of check boxes.

  4. Click the LinearLayout (Vertical) element in the palette’s Layouts group. Then click in the preview screen.

    As a result, the new LinearLayout (Vertical) element’s outline appears on the preview screen.

  5. Click the Button element in the palette’s Widgets group. Then click inside your vertical linear layout element in the preview screen.

    Voilà! Your app has a button.

    Next, you want something that aligns objects horizontally so that the check boxes are side by side.

  6. Click the LinearLayout (Horizontal) element in the palette’s Layouts group. Then click inside your vertical linear layout element in the preview screen.

    Try to place the horizontal linear layout element above the button. If you have trouble doing that, go to the Component tree and drag the LinearLayout (Horizontal) branch so that it’s above the button branch but still subordinate to the LinearLayout (Vertical) branch. (See Figure 6-2.)

    Next, you put the check boxes into your horizontal linear layout.

  7. Click the CheckBox element in the palette’s Widgets group. Then, click inside the horizontal linear layout element in the preview screen.

    If you have trouble clicking inside the horizontal linear layout, place the check box anywhere on the preview screen. Then, in the Component tree, drag the checkBox branch so that it’s subordinate to the LinearLayout (Horizontal) branch.

  8. Click the CheckBox element in the palette’s Widgets group again. Then click in the preview screen to the right of the first check box.

    Like the first check box, this second check box is inside your horizontal linear layout.

    The button and the two check boxes might not be centered side by side on the screen. You want to fix that, and I show you how in the next step.

  9. In the Component tree, select your horizontal linear layout element.

    You can try selecting this element in the preview screen but, for an element with nothing but a border, it’s easier to do the selecting in the Component tree.

  10. In the Properties panel, look for the gravity entry.

    warning Don’t confuse the layout:gravity entry with the gravity entry. They’re two different rows in the Properties tree. One of them (the layout:gravity entry) is associated with an android:layout_gravity attribute in the layout’s XML code. The other (the gravity entry) is associated with an android:gravity entry in the layout’s XML code. (I know. This couldn’t be more confusing. With any luck, the material in Book IV, Chapter 1 can help you sort it all out.)

  11. In the Properties panel, the gravity entry is a branch of a tree. Expand this branch and put a check mark in the center_horizontal item within that branch.

    The gravity property helps determine the positions of objects inside a layout (in this example, inside your horizontal linear layout element). The gravity value center_horizontal centers objects side by side within the layout. After checking the center_horizontal item, notice that the two check boxes are centered (side by side) in the preview screen.

  12. In the Component tree, select your vertical linear layout element.
  13. In the Properties panel, expand the vertical linear layout element’s gravity branch. Put a check mark in the center_horizontal item within that branch.

    When you do this, the button snaps sideways to the center of the preview screen.

    The vertical linear layout element holds the check boxes and the button, but there’s another widget in Figure 6-1. (It’s a TextView displaying the word Plain.) To make room for this additional widget, you want to tell Android that the vertical linear layout doesn’t fill up the entire screen. The next step tells you how to do that.

  14. With the vertical linear layout element still selected, look for the layout:height entry in the Properties panel.
  15. Click in the right column of the layout:height entry. In the drop-down list that appears, select wrap_content.

    As a result, your vertical linear layout element shrinks so that it’s large enough for only the two check boxes and the button.

    You have a bit more work to do, but the work isn’t burdensome.

  16. Change the text on the check boxes and the button so that it matches what you see in Figure 6-1.

    Don’t worry about the word Plain in Figure 6-1. You work on that in the section “Reusing a layout,” later in this chapter.

    For help changing the text, see to Chapter 5 of this minibook.

  17. Set the onClick property of the button to onButtonClick.

    For help setting the onClick property, see Chapter 5 of this minibook.

image

Figure 6-2: The Component tree (what you have so far, anyway).

Creating a reusable layout

The check boxes and the button in Figure 6-1 are useful in more than one situation. You might place these widgets in an app with a confirmation word (such as the word Plain in Figure 6-1). You might use the same widgets in a different app with a picture of a pizza below the widgets. One way or another, it’s worth your while to save the layout containing these widgets. You save these widgets in a new layout resource document (a blahblah.xml document in the res/layout directory). This section tells you how to do that.

  1. Open the project that you created in this chapter’s “Improving the Layout” section.
  2. In the preview screen, click in a neutral place inside the vertical linear layout that you created.

    Make sure that you see the outline of the layout that contains both check boxes and the button. If you have trouble selecting this layout, you can ignore the preview screen and select the LinearLayout (Vertical) branch in the Component tree.

  3. In Android Studio’s main menu, choose Refactor ⇒ Refactor This.

    A pop-up menu containing the Style and Layout options appears.

  4. In the pop-up menu, select Layout.

    An Extract Android Layout dialog box appears.

  5. In the dialog box’s File Name field, type the name of your new resource document.

    In Figure 6-3, I type reusable_layout.xml.

    warning The names of Android’s resource files must not contain capital letters. You can use lowercase letters and underscores. You cannot use Java’s customary “camelCase” naming convention with names like reUsableLayout.xml. And, yes, a layout filename must end with the extension .xml.

  6. Click OK to close the dialog box.

    The app/res/layout branch in the Project tool window now has a new item. If you named the file as I did in Step 5, the branch is labeled reusable_layout.xml.

  7. Double-click the reusable_layout.xml branch in the Project tool window.

    Android Studio displays the Designer tool for the reusable_layout.xml file.

  8. Make sure that the Designer tool is in Design mode (as opposed to Text mode).

    In Design mode, you can see the Component tree.

  9. Make note of the labels on the branches in the Component tree.

    Look for names like checkBox, checkBox2, and button. (See Figure 6-4.) You use these names (these id values) in the code that you write later in this chapter.

    tip To change an element’s id, double-click that element in the preview screen. The resulting pop-up menu has a text field labeled id. Change whatever is entered in that text field.

image

Figure 6-3: The Extract Android Layout dialog box.

image

Figure 6-4: The Component tree.

Congratulations! You have a group of widgets that you can use and reuse.

Reusing a layout

In the “Creating a reusable layout” section, you create a layout with check boxes and a button. You can reuse this layout in many of this chapter’s examples. Here’s how:

  1. Follow the steps in the “Creating a reusable layout” section.

    If you’re impatient, you can skip a few of that section’s steps, but be sure to create a reusable_layout.xml file and to populate the file with a few widgets.

  2. In the Project tool window, select the project’s reusable_layout.xml file.
  3. In Android Studio’s main menu, choose Edit ⇒ Copy.

    You don’t see much happening, but now your Clipboard contains a copy of the reusable_layout.xml file.

  4. Start a new Android project.
  5. In the Project tool window, select the new project’s app/res/layout branch.
  6. In Android Studio’s main menu, choose Edit ⇒ Paste.

    Now the app/res/layout branch contains a reusable_layout.xml file.

  7. Open your project’s res/layout/activity_main.xml file.

    When you do, you see your new project’s preview screen (which is mostly empty).

  8. In the Custom group in the Designer tool’s palette, click the <include> item.

    tip The palette has its own scroll bar. Use this scroll bar to find the palette’s Custom group.

    When you do this, a Resources dialog box appears. (See Figure 6-5.)

  9. In the Resources dialog box, select your reusable layout — the one you named reusable_layout.xml; then click OK.

    The Resources dialog box closes.

  10. Click in the Designer tool’s preview screen.

    As if by magic, the stuff that you created in the “Creating a reusable layout” section appears on the preview screen. (Well, anyway, it looks like magic to me.) This stuff appears as one group, so you can drag that group around in the preview screen.

  11. If necessary, reshape the newly included group (two check boxes and a button) by dragging its edges in the preview screen. Also, drag the entire group so that it’s centered inside the preview screen.

    If all goes well, your layout looks like the stuff in Figure 6-1.

    In the next step, you add the word Plain to your app’s screen. (Refer to Figure 6-1.)

  12. From the palette, place a Large Text element on the preview screen.
  13. Replace the Large Text element’s placeholder text with the word Plain.
  14. (Optional) If you’re very ambitious, follow the steps in Chapter 5 of this minibook for coding your app’s behavior. Then run your app.

    Ambitious or not, you have a decent-looking layout with a reusable component. Nice work!

image

Figure 6-5: The Resources dialog box.

Starting Another Activity

As I mention in Chapter 4 of this minibook, an Android activity is one “screenful” of components. So juggling activities is a major endeavor for Android developers. This section’s example does the simplest thing you can do with an activity — namely, make it run.

  1. Launch Android Studio and create a new project.

    In this section’s listings, I name the application 01_06_01, and I name the package com.allyourcode.p01_06_01.

  2. Follow the instructions in the earlier section “Reusing a layout” to include reusable_layout on your new app’s screen.

    You have two check boxes and a button. When a user clicks the button, you want Android to display a different activity’s screen. So you have to create another activity.

    Let’s get cracking …

  3. In the Project tool window, right-click or (on a Mac) Ctrl-click your project’s app/java/your.package branch.

    In Listing 6-1, the package name is com.allyourcode.p01_06_01. So I Ctrl-click my project’s app/java/com.allyourcode.p01_06_01 branch.

  4. In the context menu that appears, choose New ⇒ Activity ⇒ Blank Activity.

    A dialog box appears. (You see this dialog box whenever you create a new blank activity. The dialog box is labeled Choose Options for Your New File.)

  5. In the dialog box, fill in the Activity Name and Layout Name fields.

    In Listings 6-1 and 6-2, I refer to OtherActivity and other_layout. So, if you’re following along letter for letter with these instructions, type OtherActivity in the Activity Name field, and type other_layout in the Layout Name field. You can accept the defaults for all the other fields in the dialog box.

  6. Click Finish to close the dialog box.

    Your new other_layout now appears in Android Studio’s Designer tool.

  7. (Optional, but worth doing.) In this step, you don’t have to do anything. Just look at something! In your project’s AndroidManifest.xml file, notice the following code:

    <activity

    android:name=".OtherActivity"

    android:label="OtherActivity" >

    </activity>

    Android Studio added this <activity> element when you created OtherActivity in Steps 3 through 6.

    Each activity in your application must have an <activity> element in the AndroidManifest.xml file. In an <activity> element, the android:name attribute points to the name of the activity’s Java class. In this step, the attribute’s value is “.OtherActivity". The initial dot refers to the application’s package name (the name com.allyourcode.p01_06_01 from Step 1). The rest of the attribute refers to the class name in Listing 6-2.

    remember Each activity in your application must have an <activity> element. If you’re missing an <activity> element, the app can’t start that activity. (Instead, the app crashes, and you see an Unable to find explicit activity message in the Logcat panel.)

  8. With other_layout showing in the preview screen, drag a Large Text element from the palette onto other_layout.

    Now, other_layout has a TextView element (with large text).

    remember Your project has two activities (two Java files) and a layout for each activity (two XML files in the Project view’s app/res/layout branch). In addition, your project has a reusable_layout that’s included inside your main activity’s layout. You can switch back and forth between the two activities and their layout files, but try to be mindful of the switching. Try not to be become confused by editing the wrong Java code or the wrong layout file (the way I often do).

  9. Look for your new TextView element in the Component tree.

    Make note of the label on that element’s branch of the tree. In my version of the app, the label is textView3.

    techicalstuff If you switch momentarily to the Designer tool’s Text mode, you see the attribute android:id="@+id/textView3" inside the TextView tag. The id of this element is textView3.

    tip To change an element’s id, double-click that element in the preview screen. The pop-up menu that appears has a text field labeled id. Change whatever is entered in that text field.

  10. Modify your main activity’s code, as shown in Listing 6-1.

    I set the code to be added in boldface type.

    remember Double-check the expressions R.id.checkBox and R.id.checkBox2 in Listing 6-1 against the names in the Component tree at the end of the “Creating a reusable layout” section. If the Component tree’s labels aren’t checkBox and checkBox2, change your Listing 6-1 code appropriately.

    In the MainActivity (Listing 6-1), you have code that starts up the OtherActivity. You don’t start an activity by calling the activity’s methods. Instead, you create an intent. An intent is like an open-ended method call. In Listing 6-1, you create an explicit intent — an intent that invokes a specific class’s code.

    • The intent in Listing 6-1 invokes the code in a class named OtherActivity (or whatever you name your app’s second activity).
    • The intent in Listing 6-1 has two extra pieces of information. Each “extra piece” of information is a name/value pair. For example, if the user checks the Pepperoni box, pepBox.isChecked() is true, so the intent contains the extra pair "Pepperoni", true.
    • In Listing 6-1, the call startActivity(intent) invokes the OtherActivity class’s code.

    crossreference This section’s explanation of Android’s intent mechanism shows you the tiniest tip of the iceberg. To read all about activities and intents, see Book III, Chapter 2.

    Next up, your OtherActivity should have some code that responds to the fact that OtherActivity was started.

  11. In your new OtherActivity class, add the code in Listing 6-2.

    I set the code to be added in boldface type.

    warning In Listing 6-2, I assume that the TextView in the other_layout.xml file is textView3. (That is, I assume that, in the XML file itself, the TextView element has an attribute that reads android:id="@+id/textView3".) If this TextView element has an id other than textView3, change the code in Listing 6-2 accordingly.

    In Listing 6-2, the call to getIntent gets the stuff that started this activity running. So, by calling getIntent and intent.getBooleanExtra, the OtherActivity discovers the values of pepBox.isChecked() and cheeseBox.isChecked() from Listing 6-1. For example, the call

    intent.getBooleanExtra("Pepperoni", false)

    returns true if the value of pepBox.isChecked() in Listing 6-1 is true. The call returns false if the value of pepBox.isChecked() in Listing 6-1 is false. The call’s second argument is a default value. So, in Listing 6-2, the call to intent.getBooleanExtra("Pepperoni", false) returns false if the intent created in Listing 6-1 doesn’t have an extra named "Pepperoni".

  12. Run your app.

    When you click the app’s button, you see a new activity like the one pictured in Figure 6-6.

image

Figure 6-6: A new activity appears on the device’s screen.

Listing 6-1: Starting OtherActivity from the MainActivity

package com.allyourcode.p01_06_01;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.CheckBox;

public class MainActivity extends Activity {

  CheckBox pepBox, cheeseBox;

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    pepBox = (CheckBox) findViewById(R.id.checkBox);

    cheeseBox = (CheckBox) findViewById(R.id.checkBox2);

}

  public void onButtonClick(View view) {

    Intent intent =

      new Intent(this, OtherActivity.class);

    intent.putExtra

      ("Pepperoni", pepBox.isChecked());

    intent.putExtra

      ("Extra cheese", cheeseBox.isChecked());

    startActivity(intent);

  }

  // You don’t have to add any code below this point

  @Override

  public boolean onCreateOptionsMenu(Menu menu) {

  // … Et cetera

Listing 6-2: The OtherActivity

package com.allyourcode.p01_06_01;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.widget.TextView;

public class OtherActivity extends Activity {

  TextView textView;

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.other_layout);

    textView = (TextView) findViewById(R.id.textView3);

    Intent intent = getIntent();

    StringBuilder str = new StringBuilder("");

    if (intent.getBooleanExtra("Pepperoni", false)) {

      str.append("Pepperoni ");

    }

    if (intent.getBooleanExtra("Extra cheese", false)) {

      str.append("Extra cheese");

    }

    if (str.length() == 0) {

      str.append("Plain");

}

    textView.setText(str);

  }

  // You don’t have to add any code below this point

@Override

public boolean onCreateOptionsMenu(Menu menu) {

  // … Et cetera

Localizing Your App

Words, words, words. The apps in this chapter have so many words. "Pepperoni" here; "Extra cheese" there! It’s a wonder a developer can keep this stuff straight. It’s too easy to type a word one way in one part of the code and misspell the word in a different part.

You can reduce the problem by creating string constants. For example, you can write

public final String pep = "Pepperoni";

 

at the top of your Java program and use the variable pep in place of the string "Pepperoni" throughout the code. But then, to change from the English word pepperoni to the Italian word merguez, you have to mess with your Java code. In a world where only six percent of all mobile phones are in the United States,* you don’t want to edit Java code for dozens of countries.

The elegant solution to this problem is to use Android’s string externalization feature. Here’s what you do:

  1. Open the project that you created in this chapter’s “Reusing a layout” section.

    ontheweb If you’ve messed with that project since you created it, or if you didn’t faithfully execute each of my instructions in that section, don’t despair. You can find that project in the stuff that you download from my website. Visit http://allmycode.com/android and follow the instructions in Chapter 3 of this minibook for running the downloaded examples.

  2. Open the project’s reusable_layout.xml file and put the Designer tool in Text mode.

    Notice lines such as

    android:text="Extra cheese"

    in the reusable_layout.xml file? What if the user isn’t an English language speaker? A layout file describes the look of the app’s screen. The look of the screen shouldn’t depend on the user’s being able to understand what Extra cheese means.

  3. In the editor, click inside the string "Extra cheese".
  4. Press Alt-Enter.

    A pop-up menu appears. This menu is called an intention action menu. The menu contains a list of actions from which you can choose.

  5. In the intention action menu, select Extract String Resource.

    Well, wha' da' ya' know?! An Extract Resource dialog box appears! (See Figure 6-7.)

  6. In the Resource Name field, type extra_cheese.

    remember A resource name must not contain blank spaces. In this step, extra_cheese is okay and extracheese is also okay. But extra cheese isn’t okay.

  7. Click OK.

    Android Studio adds the following element to your res/values/strings.xml file:

    <string name="extra_cheese">Extra cheese</string>

    Android Studio also replaces "Extra cheese" in your layout’s CheckBox element with an @string expression:

    <CheckBox

        android:text="@string/extra_cheese"

  8. (Optional, but very nice if you do it.) Repeat Steps 3 through 7 for the strings "Pepperoni", "Show", and (in the activity_main.xml file) "Plain".

    With your app’s strings externalized, you’re ready to go international.

  9. Right-click (or on a Mac, Ctrl-click) the strings.xml file in your project’s res/values folder in the Project tool window.
  10. In the context menu that appears, select Open Translations Editor.

    The Translations Editor appears in place of the Designer tool. (See Figure 6-8.)

  11. Near the top of the Translations Editor, click the globe icon.

    A list of language locales appears. (See Figure 6-9.)

  12. Select a language locale from the list.

    For this exercise, I select Italian (it). (I’d be disloyal to my buddy Steve if I did otherwise.) For the full scoop on language locales, visit www.iso.org/iso/country_names_and_code_elements.

    As a result, the strings.xml branch in the Project tool window now has two sub-branches. Both sub-branches sport the label strings.xml, but the new sub-branch’s icon is a tiny picture of the flag of Italy. (See Figure 6-10.)

    technicalstuff Temporarily change the Project tool window from Android view to Project view. Your project’s res folder now has a values subfolder and a values-it subfolder. The values-it subfolder contains its own strings.xml file. (Okay, you can go back to the Android view now!)

    In the Translations Editor, the term extra_cheese is in red because you haven’t yet translated extra_cheese into Italian. The same is true for other terms that you haven’t yet translated.

  13. Double-click the Italian (it) column in the extra_cheese row. In that column, type Con più formaggio, and then press Enter.

    (Sorry. The Translations Editor doesn’t do any translating for you. The Translations Editor only adds code to your project when you type in the translations of words and phrases.)

  14. Repeat Step 13 for the pepperoni, show, and plain rows.

    If your Italian is a bit rusty, copy the text from the res/values-it/strings.xml file in Listing 6-3.

  15. Test your app.

    As with most devices, the emulator has a setting for Language & Input. Change this setting to Italiano (Italia), and suddenly, your app looks like the display in Figure 6-11.

image

Figure 6-7: The Extract Resource dialog box.

image

Figure 6-8: The Translations Editor.

image

Figure 6-9: Select a language.

image

Figure 6-10: Look! You have two strings.xml files.

image

Figure 6-11: Buongiorno!

Elenco 6-3: Benvenuto in Italia!

<?xml version="1.0" encoding="utf-8"?>

<resources>

    <string name="hello">

        Ciao mondo, la mia attività!</string>

    <string name="app_name">

        Il mio secondo progetto Android</string>

    <string name="extra_cheese">Con più formaggio</string>

    <string name="pepperoni">Merguez</string>

    <string name="plain">Semplice</string>

    <string name="show">Mostra</string>

</resources>

Responding to Check Box Events

Why click twice when you can do the same thing by clicking only once? Think about the example in the previous section. Your app responds to the contents of check boxes when the user clicks a button. In a streamlined scenario, your app might respond as soon as the user checks a box. Listing 6-4 shows you how to make this happen.

Listing 6-4: Responding to CheckBox Events

package com.allyourcode.p01_06_04;

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.widget.CheckBox;

import android.widget.CompoundButton;

import android.widget.CompoundButton.

            OnCheckedChangeListener;

import android.widget.TextView;

public class MainActivity extends Activity

            implements OnCheckedChangeListener {

  TextView textView;

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    ((CheckBox) findViewById(R.id.checkBox))

      .setOnCheckedChangeListener(this);

    ((CheckBox) findViewById(R.id.checkBox2))

      .setOnCheckedChangeListener(this);

    textView =

      (TextView) findViewById(R.id.textView);

  }

  @Override

  public void onCheckedChanged(CompoundButton box,

      boolean isChecked) {

    StringBuilder str =

      new StringBuilder(textView.getText());

    CharSequence boxText = box.getText();

    if (isChecked) {

      str.append(" " + boxText);

    } else {

      int start = str.indexOf(boxText.toString());

      int length = boxText.length();

      str.replace(start, start + length, "");

    }

    textView.setText(str.toString().trim());

  }

//… Et cetera

 

Like a button, each check box listens for onClick events. So you can write this section’s code very much like the code in Listing 6-1. But in this section’s listing, I avoid using the onClick property and illustrate the use of a different event listener.

A check box listens for changes to its state (its “checked” versus “unchecked” state). So when the user touches a check box, Android fires an onCheckedChanged event. By registering this (the entire MainActivity instance) as each check box’s OnCheckedChangeListener, you make Android call the onCheckedChanged method in Listing 6-4.

The onCheckedChanged method has two parameters — the component that was touched and the state of the component as a result of the touch. I’ve contrived the code in Listing 6-4 to make use of these two method parameters.

technicalstuff A CompoundButton is a widget with checked and unchecked states. The CheckBox class is a subclass of CompoundButton. Other subclasses of CompoundButton are RadioButton and ToggleButton. A ToggleButton is that cute little thing that lights when it’s checked.

In Listing 6-4, the onCheckedChanged method’s box parameter refers to whichever check box the user touches. That check box has a getText method, so in Listing 6-4, I use the getText method to help fill the textView element. I use the onCheckedChanged method’s isChecked parameter to decide whether to add text to the textView element or delete text from the textView element.

Displaying Images

After designing an app and its variations in the previous sections, you may decide that your app needs some flair. How about designing your app so that when a user clicks a button, your app displays a picture of the pizza being ordered? The SHOW button in Figure 6-1 is perfect for this.

Android has all kinds of features for drawing images and displaying bitmap files. I cover many of these features in Book IV, Chapter 3. In this section, I cover one possible approach:

  1. Launch Android Studio and create a new project.

    In this section’s listings, I call the project 01_06_05, and I use the package com.allmycode.p01_06_05.

  2. Copy the reusable_layout.xml file from this chapter’s “Creating a reusable layout” section to your new project’s app/res/layout branch in the Project tool window.
  3. Include reusable_layout in your project’s activity_main.xml file.

    For details, see Steps 7 through 11 in the section “Reusing a layout.”

  4. Find four images — one for plain, one for pepperoni, one for extra cheese, and one for pepperoni with extra cheese.

    Android’s official documentation recommends the .png format for images. If you don’t have .png images, Android’s docs call the .jpg format “acceptable.” If you don’t have .png or .jpg, the docs tell you to hold your nose and use .gif. But remember, in this section, you’re creating a practice application, not a work of art. Your images don’t have to look good. They don’t even have to look like pizzas. Besides, you can download my silly-looking drawings of pizzas from this book’s website at www.allmycode.com/Android.

    In creating my project, I use the filenames plain.png, pepperoni.png, extracheese.png, and pep_extracheese.png.

    remember The names of Android’s resource files must not contain capital letters. You can use only lowercase letters and underscores.

    tip For working with image formats, the program IrfanView has always served me well. You can get this Windows program at http://www.irfanview.com. The program is free for noncommercial use.

  5. In your operating system’s File Explorer or Finder, select the image files. Then, in the main menu, choose Edit ⇒ Copy.
  6. In Android Studio’s Project tool window, select the app/res/drawable branch.
  7. In the main menu, choose Edit ⇒ Paste.

    A Choose Destination Directory dialog box appears.

  8. In the Choose Destination Directory dialog box, select the drawable branch (as opposed to one of the drawable-dpi branches), and then click OK.

    In a real-life app, you use the drawable-dpi directories as alternatives for devices with high, medium, extra-high, and extra-extra-high screen densities. But in this practice app, a default drawable folder is the easiest to use.

    technicalstuff The letters dpi stand for dots per inch. Android senses a device’s screen density and uses the resources in the most appropriate drawable-?dpi folder. To find out what Android considers “most appropriate,” visit http://developer.android.com/guide/practices/screens_support.html.

  9. Right-click (on Windows) or Ctrl-click (on a Mac) the app/res/drawable branch.
  10. In the menu that appears, select New ⇒ File.

    Once again, the Choose Destination Directory dialog box rears its ugly head.

  11. Select the drawable branch, and then click OK.

    A New File dialog box appears. This dialog box has only one field — a field for the name of your new file. (See Figure 6-12.)

  12. In the New File dialog box’s field, type levels.xml.
  13. Click OK to dismiss the New File dialog box.
  14. Use Android Studio’s editor to populate your levels.xml file with the code in Listing 6-5.

    A level-list is a list of alternative drawables for a single image component to display. At any moment during an app’s run, the image component has an integer level. You set the component’s level using the setImageLevel method.

    When your app calls setImageLevel, Android starts at the top of the level-list and looks for the first item whose android:maxLevel is greater than or equal to the new image level. You can also assign an android:minLevel attribute to an item. But in most situations, android:maxLevel is all you need.

  15. Add an ImageView element to your activity’s layout.

    You can drag an ImageView element from the Widgets group in the Designer tool’s palette, or you can add the following element to your app’s activity_main.xml file:

    <ImageView android:id="@+id/imageView1"

        android:layout_height="wrap_content"

        android:layout_width="wrap_content"

        android:src="@drawable/levels"></ImageView>

  16. Make sure that your ImageView element’s android:src attribute refers to your new levels.xml file.

    In the src entry in the Properties view, look for the value @drawable/levels.

  17. Code your project’s activity file as in Listing 6-6.

    In Listing 6-6, the onButtonClick method calls the setImageLevel method. The method parameter’s value depends on the states of the activity’s check boxes.

  18. Run the app.

    The results, along with my beautiful drawings of pizza with toppings, are shown in Figure 6-13.

image

Figure 6-12: The New File dialog box.

image

Figure 6-13: What lovely drawings!

Listing 6-5: A Level-List Document

<?xml version="1.0" encoding="utf-8"?>

<level-list xmlns:android=

        "http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/plain"

          android:maxLevel="0" />

    <item android:drawable="@drawable/pepperoni"

          android:maxLevel="1" />

    <item android:drawable="@drawable/extracheese"

          android:maxLevel="2" />

    <item android:drawable="@drawable/pep_extracheese"

          android:maxLevel="3" />

</level-list>

Listing 6-6: Changing Images

package com.allmycode.p01_06_05;

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.CheckBox;

import android.widget.ImageView;

public class MainActivity extends Activity {

  CheckBox pepBox, cheeseBox;

  ImageView imageView;

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    pepBox =

      (CheckBox) findViewById(R.id.checkBox);

    cheeseBox =

      (CheckBox) findViewById(R.id.checkBox2);

    imageView =

      (ImageView) findViewById(R.id.imageView);

  }

  public void onButtonClick(View view) {

    int level = 0;

    if (pepBox.isChecked()) {

      level += 1;

    }

    if (cheeseBox.isChecked()) {

      level += 2;

    }

    imageView.setImageLevel(level);

  }

  // You don’t have to add any code below this point

  @Override

  public boolean onCreateOptionsMenu(Menu menu) {

  // … Et cetera

Sending in Your Order

If you’ve read any of this chapter’s previous sections, you’re probably very hungry. An app with nothing but pictures and the names of pizza toppings is a real tease.

So you’d better add some purchasing power to this chapter’s example. Real e-commerce functionality is the subject of several other books. But in this book, you can get a small taste of the online pizza-ordering process (pun intended). You can submit your choice of toppings to an existing web server — Google’s search engine, to be precise. It’s not as good as biting into a tasty pizza, but the example shows you one way to send information from a mobile device.

In a real application, you might program your own server to respond intelligently to users' requests. For passing money back and forth, you might use the Google Play Store’s in-app billing facilities.

crossreference Programming web servers isn’t an Android-specific topic. To read all about servers, check out Apache, MySQL, and PHP Web Development All-in-One Desk Reference For Dummies, by Jeff Cogswell (John Wiley & Sons, Inc.).

  1. Launch Android Studio and create a new project.

    In this section’s listing, I call the project 01_06_07, and I use the package com.allmycode.p01_06_07.

  2. Copy the reusable_layout.xml file from this chapter’s “Creating a reusable layout” section to your new project’s app/res/layout branch in the Project tool window.
  3. Include reusable_layout in your project’s activity_main.xml file.

    For details, see Steps 7 through 11 in the section “Reusing a layout.”

  4. Get a WebView element from the Widgets group of the Designer tool’s palette. Place that WebView element anywhere on your app’s preview screen.

    A WebView is a mini web browser that you can add to an existing activity.

    It doesn’t matter how you position the WebView element on the screen. When the user visits a web page, the page will take up the entire screen. (If you want the page to appear below your check boxes and button, you’ll have to see Chapter 1 in Book IV.)

  5. Code your project’s activity file as in Listing 6-7.
  6. Add the following element to your project’s AndroidManifest.xml file:

    <uses-permission

    android:name="android.permission.INTERNET" />

    Make this uses-permission element a direct sub-element of the document’s manifest element.

    The uses-permission element grants your app permission to access the Internet. Access to the Internet will appear in the list the user sees before installing your app.

    remember When you create an app, don’t forget to add the appropriate permissions to the app’s AndroidManifest.xml file. In a recent survey of For Dummies book authors, all respondents reported that they frequently forget to add permissions to their apps' manifest files. (Survey sample size: one.)

  7. Run your app.

    You might have to wait for the web page to load. When the page loads, your app looks something like the screen in Figure 6-14.

image

Figure 6-14: Your app sends stuff to a web server.

Listing 6-7: Sending Info to a Server

package com.allmycode.p01_06_07;

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.webkit.WebView;

import android.widget.CheckBox;

public class MainActivity extends Activity {

  CheckBox pepBox, cheeseBox;

  WebView webView;

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    pepBox = (CheckBox) findViewById(R.id.checkBox);

    cheeseBox = (CheckBox) findViewById(R.id.checkBox2);

    webView = (WebView) findViewById(R.id.webView);

  }

    public void onButtonClick(View view) {

      StringBuilder str = new StringBuilder("");

      if (pepBox.isChecked()) {

         str.append("Pepperoni");

      }

      if (cheeseBox.isChecked()) {

      str.append(""Extra cheese"");

      }

      if (str.length() == 23) {

      str.insert(9, '+');

      }

      if (str.length() == 0) {

      str.append("Plain");

      }

      webView.loadUrl

      ("http://www.google.com/search?q="+str.toString());

  }

  // You don’t have to add any code below this point

  @Override

  public boolean onCreateOptionsMenu(Menu menu) {

  // … Et cetera

Notes

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

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