User Tools

Site Tools


android_learning:headfirst_android_development_notes:chapter_6

Chapter 6 notes

When creating Activities in Android Studio 1.5, if you specify an Empty rather than a Blank layout template, you will get template code that is very similar to what HFAD bases all its code on. This should allow you to use the book's code without modification. However, it will remove template code for some newer Activity features.

The notes that follow assume you are creating Empty Activities.

p. 235: LinearLayout

You wouldn't know it yet, but the main layout for the app in this chapter uses a LinearLayout with a vertical option rather than a RelativeLayout. You may as well make the change now:

activity_top_level.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.hfad.starbuzz.TopLevelActivity"
    android:orientation="vertical">
 
    ...
 
</LinearLayout>

Unlike the book, I've left the padding in place in my code as I think the app looks better this way.

p. 236: Code block

Drink.java
package com.hfad.starbuzz;
public class Drink {
    private String name;
    private String description;
    private int imageResourceId;
    //drinks is an array of Drinks
    public static final Drink[] drinks = {
            new Drink("Latte", "A couple of espresso shots with steamed milk",
                    R.drawable.latte),
            new Drink("Cappuccino", "Espresso, hot milk, and a steamed milk foam",
                    R.drawable.cappuccino),
            new Drink("Filter", "Highest quality beans roasted and brewed fresh",
                    R.drawable.filter)
    };
    //Each Drink has a name, description, and an image resource
    private Drink(String name, String description, int imageResourceId) {
        this.name = name;
        this.description = description;
        this.imageResourceId = imageResourceId;
    }
    public String getDescription() {
        return description;
    }
    public String getName() {
        return name;
    }
    public int getImageResourceId() {
        return imageResourceId;
    }
    public String toString() {
        return this.name;
    }
}

Take special note of what the book says with hand scribbled notes about image resources.

p. 237: Using images

To use images in Android apps,

  • Place image files in app/src/main/res/drawable (or special subdirectories).
  • Use filenames that consist only of lowercase letters and the underscore character (plus the file extension).
  • The drawable resources will then be available in code as R.drawable.<filename-without-extension>.

You can add the files within Android Studio (drag and drop) or by using a file manager (MS File Explorer, Mac Finder, Linux Nautilus and Thunar, etc.).

p. 239

If you use Android Studio's assistance to specify @array/options, it will by default place the values in arrays.xml instead of strings.xml:


You'll find it easier if you add the needed string-array to strings.xml manually.

pp. 241-243

In case the event listener code has you a little flummoxed, here's a slightly simpler version of the event handling. Instead of launching an Intent, it simply Toasts with the value of the list item that was clicked.

TopLevelActivity.java
package com.hfad.starbuzz;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
 
public class TopLevelActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_top_level);
 
        // Make an OnItemClickListener that Toasts when you click on an item.
        AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast whichItemToast = Toast.makeText(view.getContext(),
                    "Item position: " + position,
                    Toast.LENGTH_SHORT);
                whichItemToast.show();
            }
        };
 
        // Set the top-level ListView's item click listener to OnItemClickListener created above.
        ListView listView = (ListView) findViewById(R.id.list_options);
        listView.setOnItemClickListener(itemClickListener);
    }
}

Once you wrap your head around this, you should be able to change the code to launch the Intent in the book (whose Activity is yet to be created).

p. 249: Creating a ListActivity

When you create a new Activity that will become a ListActivity, you'll need to

  • Change … extends Activity … to … extends ListActivity…
  • Remove the call to setContentView() in the constructor.
  • Delete the layout file(s) that were generated for this Activity.

The last item is optional. A ListActivities has layouts build into it; however, you can override them.

Be sure to add the @string/title_activity_drink_category resource, and make up a reasonable name for the value.

p. 250-252: Adapters

The Adapter is a software engineering design pattern. The essence of an Adapter object is that it functions as “glue” between two different objects. The most common application is to translate between a client and a source of data (e.g., a database). You can read more about the Adapter design pattern here.

In the DrinkCategoryActivity, the client is the DrinkCategoryActivity itself and the source of data is the static array of Drinks defined in Drink.java.

The source of data for the DrinkCategoryActivity might seem to be over-engineered. Why create a class to encapsulate different drinks and put them into an array in the the class definition? The answer to this will unfold later in the app (we'll need an array of objects rather than an array of e.g. strings). And in a future chapter, we'll see other benefits to defining a class to represent your data objects and data containers.

In the meantime, here's a version of the ArrayAdapter code that adapts a simple string array for use with the ListView instead of the Drink.dinks array.

A ListActivity has a ListView built into it.

To get a reference to a ListActivity's ListView, use the ListActivity's getListView() method.

DrinkCategoryActivity.java
package com.hfad.starbuzz;
 
import android.app.ListActivity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
 
public class DrinkCategoryActivity extends ListActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        // Array of strings that will be adapted to this ListActivity's
        // ListView:
        String[] coffees = new String[]{
                "Sucrose enhanced",
                "Fat and lactose enhanced",
                "The works",
                "The right way"
        };
 
        // Make an Adapter for string arrays:
        ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(
                this,
                android.R.layout.simple_list_item_1,
                coffees
        );
 
        // Attach the Adapter to the ListView used by this ListActivity:
        ListView listDrinks = getListView(); // i.e., this.getListView();
        listDrinks.setAdapter(listAdapter);
    }
}

pp. 257-258

To process user clicks on a ListActivity, you need to override the ListActivity's onListItemClick method. Android Studio has support for easily adding overridden methods to class definitions:

  1. Right click where you want the overridden method to be and click on Generate…
  2. Click Override methods…
  3. Browse for the method you want to override, select it, and click OK.

DrinkActivity.class and DrinkActivity.EXTRA_DRINKNO aren't created until p. 263. Therefore, if you add the code on pp. 257-258 to your project, Android Studio will show you lots of red anger and prevent you from building it.

Instead, you may want to experiment with a handler that (again) just makes a Toast:

    // Show a Toast when an item is clicked
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        Toast aToast = Toast.makeText(
            v.getContext(), 
			"Item position: " + position,
			Toast.LENGTH_SHORT
		);
        aToast.show();
    }

.

p. 263

In the code here, you can see the advantage of creating a class to represent and contain your data. It makes accessing an object and all pertinent data related to the object much easier.

p. 268

I would add to the first point (“Sort your ideas …”) that you should use a top-level/category/detail-edit structure only if it makes sense for your app! It's a good paradigm, but it's by no means universal.

android_learning/headfirst_android_development_notes/chapter_6.txt · Last modified: 2016/01/31 21:20 by mithat

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki