====== 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: ... 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 ===== 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.''. 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'': {{youtube>PkFn13kh9ZA?large&rel=0}}\\ 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. 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 [[https://sourcemaking.com/design_patterns/adapter|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 [[http://developer.android.com/reference/android/app/ListActivity.html#getListView()|getListView()]] method. 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 listAdapter = new ArrayAdapter( 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: {{youtube>hcpktO1OZ_8?640x480&rel=0}} - Right click where you want the overridden method to be and click on //Generate...// - Click //Override methods...// - 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.