User Interface and Handlers Goal: Create an easy to use, intuitive, immersive experience • Can be done in code (like in Swing) – Similar to previous generation UI API's (like Swing, AWT) – Painful with lots of lines of code – Five times more statements than XML version • Normally done in XML and strongly advised – – – – Progressive enhancement/Model-View (like JavaFX) Easier to maintain, lots less code and separate from source Can create specialized views for different environments Store layout files as text in resource subdirectories • res/layout: The default version • res/layout-landscape, res/layout-fr-small User Interface Example • This application contains a series of labels presented vertically. • There is an outer container and two inner containers • The second inner container contains two lower level sub-containers Layout File Structure <?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"> <!-- NAME CONTAINER XML goes here --> <!-- ADDRESS CONTAINER goes here --> </LinearLayout> Notes 1. 2. 3. 4. 5. 6. Shown is the outer container: like a frame in Java Linear layout is similar to BoxLayout in Java fill_parent means expand to use all the space provided by the parent container Android > 2.2: fill_parent is deprecated; replaced by match_parent "http://schemas.android.com/apk/res/android" contains XML android schema Layouts and views can be nested, but keep the nesting to a minimum for maximum performance Name Container Shown as a comment in the previous slide <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Name:" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="John Doe" /> </LinearLayout> Notes • Use all available space horizontally and only the space needed vertically • This example uses hard-coded text, which is possible, but not advisable • TextView in this example is similar to Java JLabel components Address Container Shown as a comment in the previous slide <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Address:" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="911 Hollywood Blvd." /> </LinearLayout> Notes • Use all available space horizontally and only the space needed vertically • Two sub views (components) containing text strings Using String ids <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent“ android:layout_height="wrap_content"> <TextView android:id="@+id/nameText" android:text="@string/name_text" android:layout_width="wrap_content“ android:layout_height="wrap_content"/> <TextView android:id="@+id/nameValue" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> Notes 1. 2. 3. @string/name_text refers to a strings.xml entry in res/values/strings.xml <string name="name_text">Name:</string> The + in @+id/nameValueText adds a code for nameValueText if not defined Java Access: TextView name = (TextView)findViewById(R.id.nameValue); namevalue.setText("John Doe"); Text Views • TextView: Like a smarter Java Jlabel – Attribute: android:autoLink= "email|web|phone|map" • Creates hyperlink, initiates a phone call, or draws a map • Code: (TextView)findViewById(R.id.tv).setAutoLinkMask(Linkify.ALL); – Other attributes: android:minLines, android:maxLines, etc. • EditText: Like Java JTextField with additional capabilities – Autocorrection for captalizing text, etc. – Able to validate syntax for phone numbers, emails, etc. – Display field hints: android:hint="@string/someHint" or setHint() – Additional attributes like android:textMultiLine, etc. • AutoCompleteTextView: Suggestions based on a supplied array of strings • MultiAutoCompleteTextView: Suggestions during text entry after token boundaries (like commas, spaces, and periods). EditText Example <EditText android:inputType="textMultiLine" <!-- Multiline input --> android:lines="8" <!-- Total Lines prior display --> android:minLines="6" <!-- Minimum lines --> android:gravity="top|left" <!-- Cursor Position --> android:maxLines="10" <!-- Maximum Lines --> android:layout_height="wrap_content" <!– Content determines height --> android:layout_width="fill_parent" <!-- Fill entire width --> android:scrollbars="vertical" <!-- Vertical Scroll Bar --> android:hint="@string/email_hint" android:inputType="textEmailAddress" /> Button Controls • Button (Example launches browser) Button btn = (Button)this.findViewById(R.id.btn); btn.setOnClickListener(new OnClickListner()) { Intent intent = new Intent(Intent.ACTION_VIEW, URI.parse("http://www.sou.edu)); startActivity(intent); }); • ImageButton: Clickable image (or icon) in res/drawable directory <ImageButton android:id="@+id/imageBtn" android:src="@drawable/btnImage" android:layout_width="wrap_content" android:layout_height="wrap_content" /> • ToggleButton: Switch from on to off on each click, bar shows green if on <ToggleButton android:id="@+id/cctglBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" Android:textOn="Stop" Android:textOff="Run" android:text="Toggle Button"/> Checkbox Buttons <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:text="Chicken" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <CheckBox android:text="Fish" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <CheckBox android:text="Steak" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> Radio Buttons <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <RadioGroup android:layout_width="wrap_content" android:layout_height="wrap_content"> <RadioButton android:id="@+id/chRBtn" android:text="Chicken" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <RadioButton android:id="@+id/fishRBtn" android:text="Fish" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <RadioButton android:id="@+id/stkRBtn" android:text="Steak" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </layout> Other Android Controls • ImageView: <ImageView android:id="@+id:myImageCode" /> – Display a color: anroid:src="#555555" – Display an image: android:src="@drawable/manatee" android:scaleType="centerInside" – Specify a picture not in the res/drawable directory ImageView img = (ImageView)findViewById(R.id.myImageCode); img.setImageUri(Uri.fromFile(new File("/sdcard/cats.jpg"))); • • • • DatePicker, TimePicker: Select a date,time using dropdown menus DigitalClock: Display a digital clock updating automatically MapView: Display a Google map WebView: Display HTML/JavaScript from an Android native application Layout Managers A view that controls how the sub-views are arranged • LinearLayout – components arranged horizontally or vertically – Similar to Java BoxLayout • TableLayout – Specify rows and columns – Similar to laying out HTML tables • RelativeLayout: positioning relative to other components – layout_centerInParent, alignParentTop, alignParentBottom – layout_above, layout_toRightOf, layout_toLeftOf, layout_below • FrameLayout – Multiple components in the same space – Similar to Java OverlayLayout and CardLayout TableLayout Example One row/ three columns Stretch to fill entire width <TableLayout xmlns:android=http://schemas.android.com/apk/res/android android:layout_width="fill_parent" android:layout_height="fill_parent" android:stretchColumns="0,1,2"> <EditText android:text="Full Name:"/> <TableRow> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Barack"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hussein"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Obama"/> </TableRow> android:layout_span="2" to span two view columns </TableLayout> Example: FrameLayout Only the first picture is visible Similar to Java OverlayLayout <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/frmLayout" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+id/one" android:src="@drawable/one" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitCenter" /> <ImageView android:id="@+id/two" android:src="@drawable/two" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitCenter" android:visibility="gone" /> </FrameLayout> Android Code for Frame Layout @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.frame); ImageView one = (ImageView)this.findViewById(R.id.one); ImageView two = (ImageView)this.findViewById(R.id.two; one.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { ImageView two=(ImageView) FramelayoutActivity.this.findViewById(R.id.two); two.setVisibility(View.VISIBLE); view.setVisibility(View.GONE); }}); two.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { ImageView one=(ImageView)FramelayoutActivity.this.findViewById(R.id.one); one.setVisibility(View.VISIBLE); view.setVisibility(View.GONE); }}); } Merging Directly into Parent View Note: no fill specifications ?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" <ImageView android:id="@+id/one" android:src="@drawable/one" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitCenter" /> <ImageView android:id="@+id/two" android:src="@drawable/two" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitCenter" android:visibility="gone" /> </merge> Frame Layout Example <FrameLayout xmlns:android =http://schemas.android.com/apk/res/android android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="center" android:src="@drawable/golden_gate" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dip" android:layout_gravity="center_horizontal|bottom" android:padding="12dip“ android:background="#AA000000" android:textColor="#ffffffff" android:text="Golden Gate" /> </FrameLayout> Frame Inefficiency Solution Eliminate extra layout by merging with parent <merge xmlns:android="http://schemas.android.com/apk/res/androi d"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="center" android:src="@drawable/golden_gate" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dip" android:layout_gravity="center_horizontal|bottom" android:padding="12dip" android:background="#AA000000" android:textColor="#ffffffff" android:text="Golden Gate" /> Reusable layouts Inserting one layout into another <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include android:id="@+id/my_actionbar" layout= "android:layout/actionbar" /> <include android:id= "@+id/my_image_text_layout" layout = "@layout/image_text_layout" /> </LinearLayout> Lazy Includes <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/myListView" android:src="@drawable/one" android:layout_width="fill_parent" android:layout_height="fill_parent“ /> <ViewStub android:id="@+id/progress" android:inflateId="@+id/progress_inflate" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity= "bottom" android:layout= "@layout/progress_panel" /> </FrameLayout> Corresponding Java Code View stub = findViewById(R.id.progress_inflate); Stub.setVisibility(true); Later: Stub.setVisibility(false0; A ViewStub is an invisible, zero-sized View that inflates only if needed Weight and Gravity • Weight: Sizing a component in a view – Controls size relative to other components – Android:layout_weight – Components with large weights expand more • Gravity: Component alignment – android:gravity: applies to the text within a view – android:layout_gravity: applies to the view alignment – Possible values: "right", "left", "center", "top", "bottom", "center_vertical", "clip_horizontal" Padding Definition: Space around the text <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android android:orientation="vertical" android:layout_width="fill_parent“ android:layout_height="fill_parent"> <EditText android:layout_width="wrap_content" android:text="one" android:layout_height="wrap_content" android:padding="40px" /> </LinearLayout> Measurements • Well known measurements: Pixels: px, Inches: in, Millimeters: mm, Points: pt (1/72 of an inch) • Density-independent pixels: dip or dp based on a 160-dp screen size • Scale-independent pixels: sp scales dp to font sizes if Font size is normal normal, sp=dp; if font size is large, sp>dp Density Independent pixels • Physical screen width 1.5 inches • Lower resolution screen – – – – Dots Per Inch (dpi) 160 Pixels 240 (width * dpi) Density 1.0 (dpi/160) Density Independent pixels 160 (160 * density) • Higher resolution – – – – Dots Per Inch (dpi) 240 Pixels 360 (width * dpi) Density 1.5 (dpi/160) Density Independent pixels 240 (160 * density) Complex Views Displays a set of data using a single view • ListView: A scrollable list displayed vertically • GridView: A scrollable list of items displayed with a fixed number of columns • SpinnerView: (Like a Java combo box) A scrollable drop down menu of choices • GalleryView: Horizontally scrollable list focusing on the center of the list Note: Analogous to Swing JTree, JList, JTable components AdapterViews • Purposes – Connect a complex view to the data – Define the display format of a particular cell, which can contain a variety of sub views – Reuse the cell layout component for memory, performance efficiency • Adapters Required Because: It is unworkable to display a large lists with thousands of components, each requiring megabytes of memory. • Definition: An Adapter object is a bridge between a view and the data that view displays. The Adapter provides access to the data items. The Adapter is also responsible for displaying each data set item • Built in Adapters – ArrayAddapter: Data items stored in an array – SimpleCursorAdapter: Data are rows of an SQL table – Custom Adapters: A new class that overrides various adapter methods Activity using ArrayAdapter public class MyActivity extends Activity { private ArrayAdapter<String> instance; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // main.xml in res/layout ListView view = (ListView)findViewById(R.id.my_list_view); // scrollable list ArrayList<String> words = new ArrayList<String> // create some data (Arrays.asList("the", "quick", "green", "Android", "jumped“); int layoutID = android.R.layout.simple_list_item_1; // format of list items adapter = new ArrayAdapter<String>(this, layoutID, words); view.setAdapter(adapter); // Attach array adapter to the list adapter.notifyDataSetChanged(); // force redisplay of items } } Item class for a To Do list Application public class ToDoItem { String task; Date created; SimpleDataFormat sdf; public ToDoItem(String task, Date created) { sdf = new SimpleDateFormat("dd/mm/yy"); task = this.task; created = this.created; } public ToDoItem(String task) { this(task, new Date(java.lang.System.currentTimeMillis())); } public String getTask() { return task; } public Date getCreated() { return created; } @Override public String toString() { return "("+sdf.format(created)+") "+task; } } Goal: display a list of these To Do items public class ToDoItemAdapter extends ArrayAdapter<ToDoItem> { private int resource; private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy"); private String INFLATER = Context.LAYOUT_INFLATER_SERVICE; public ToDoItemAdapter(Context context, int resource, List<ToDoItem> items) { super(context, resource, items); this.resource = resource; } @Override public View getView(int position, View view, ViewGroup parent) { LinearLayout myView; ToDoItem item = getItem(position); String taskString = item.getTask(); Date createdDate = item.getCreated(); String dateString = sdf.format(createdDate); if (view == null) { myView = new LinearLayout(getContext()); LayoutInflater li=(LayoutInflater)getContext().getSystemService(INFLATER); li.inflate(resource, myView, true); } else { myView = (LinearLayout) view; } myView.findViewById(R.id.rowDate).setText(dateString); myView.findViewById(R.id.row).setText(taskString); return myView; Custom Adapter Code Menu Categories • Regular option menus: Activity associated (onCreateOptionsMenu()) • Action Bar Actions: Menu items shown on the action bar • Secondary menus: Rarely used menu items created separately from the parent menu appearing after regular menu items • Submenus: A menu within a menu that appears in a floating window; options appear when the user selects a parent item • Context menus: triggered by a long press on a view • Popup menus: An alternate way to attach menus to a view • Icon menus: List of icons displayed along the screen bottom • Alternative menus: Menu items from other applications included as a menu option Note: When more menu items exist than can show, a more button appears Option Menu Framework Classes: android.view.Menu, android.view.SubMenu, android.view.MenuItem Regular Menu From XML XML in file game_menu.xml <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:id="@+id/menuGroup"> // Group of items tied together <item android:id="@+id/new_game" android:title="@string/new" /> <item android:id="@+id/help" android:title="@string/help" /> <group> </menu> Java Code to include the menu @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // Allow for system menu items MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.game_menu, menu); return true; // Force menu to be visible } Note: Android calls onPrepareMenuOption every time a menu is invoked. Overriding this method enables dynamically changing menu items. Menu Groups • Definition: A sequence of items from a men • Purpose: Control all grouped items at once • Examples: – menu.setGroupCheckable(id, checkable, exclusive): Check selected items; if exclusive, only one group item can be checked – menu.setGroupEnabled(id, enabled): Control ghosted items – menu.setGroupVisible(id, visible): Show or hide the group items – menu.removeGroup(id): Remove all items from the group Creating a Menu in Code • Regular menu items int group = Menu.FIRST, order=Menu.FIRST, menuID = 99; menu.add(group, menuID++, order++, "append"); menu.add(group, menuID++, order++, "clear"); • Secondary menu items int group = Menu.CATEGORY_SECONDARY int order=Menu.FIRST, menuID = Menu.FIRST; menu.add(group, menuID++, order++, "secondary item #1"); menu.add(group, menuID++, order++, R.string.secItem2); • Java Setup code @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // Allow for system menu items addRegularMenuItems(menu); addSecondaryMenuItems(menu); return true; // Force menu to show } Respond to Menu Item Selections Android calls onOptionItemSelected method when an item is selected @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.new_game: newGame(); return true; // consume this selection here case R.id.help: showHelp(); return true; // consume this selection here case R.id.secondary: this.myMenu.setGroupVisible(Menu.CATEGORY_SECONDARY, true); return true; // consume this selection here default: return super.onOptionsItemSelected(item); } } Icon Menus • In XML: android:icon="@drawable/ballons" • In Code: item.setIcon(R.drawable.balloons); • Restrictions – Will not appear on expanded menu options (those which show only when the more button is selected) – Check marks are not supported Submenus • In XML: <item android:title="Outer Menu Item> <menu><item> . . .</item></menu> • In Code: int base = Menu.FIRST; ∙ ∙ ∙ SubMenu sub = menu.addSubMenu(base, item++ ,Menu.NONE, "submenu"); sub.add(base, order++, menuID++, "sub item # 1"); sub.add(base,order++, menuID++, R.string.subItem2 ); • Restrictions – Icons work with submenus, but not with individual submenu items – You cannot nest a submenu to a submenu • Advantage: Android automatically controls the visibility • Note: The order argument is optional; Menu.NONE indicates a default order. Context Menus onContextItemSelected() View Context Menu Creation • Ownership: view • Creation: Activity – Register in the activities onCreate method @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView tv = (TextView)this.findViewById(R.id.textViewId); registerForContextMenu(tv); // Indicate that view has context menu } – Populate: (note: info can get position for complex views) onCreateContextMenu(ContextMenu m, View v, ContextMenuInfo info) – Listener: onContextItemSelected(MenuItem item) Popup Menu It displays when touching the image, It disappears when selecting an item or touching outside its bounds • Specify in an XML view declaration <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_overflow_holo_dark" android:contentDescription="@string/descr_overflow_button" android:onClick="showPopup" /> • Activity code to display the popup public void showPopup(View v) { PopupMenu popup = new PopupMenu(this, v); MenuInflater inflater = popup.getMenuInflater(); inflater.inflate(R.menu.actions, popup.getMenu()); popup.show(); } // Note: R.menu.actions refers to the XML menu declaration Alternative Menus • Application menus with items pointing to other applications for retrieval or manipulation of particular data types • Content Providers expose data by defining a MIME type and a content URI access point for other applications • Example: (The application Employees maintains employee data) 1. MIME type: vnd.android.cursor.item/mina.android.Emps 2. Other application can access the data by calling the Uri content://mina.android.Emps/All access all employees or the Uri content://mina.android.Emps/1 access a single employee instance • An alternative menu item in Application A, when clicked, launches the employee data activity through the Uri to perform calculations The Employee Content Provider • The content provider defines an activity with the AndroidManifest.xml file can handle employee requests <activity android:name=".Demo“ android:label="@string/app_name"> <intent-filter android:label="Access Employees"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.ALTERNATIVE" /> <data android:mimeType="vnd.android.cursor.item/mina.android.Emps" /> </intent-filter> </activity> • This activity will respond to implicit application intents with Action: Intent.ACTION_VIEW. Category: android.intent.category.ALTERNATIVE. MIME type: vnd.android.cursor.item/mina.android.Emps Alternative Menu Code public boolean onCreateOptionsMenu(Menu menu) { menu.add("Regular item"); //adds a regular menu item //create intent with the employee content provider Uri Intent launch = new Intent(Intent.ACTION_VIEW, Uri.parse("content://mina.android.Emps/All")); target.addCategory(Intent.CATEGORY_ALTERNATIVE); menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, //item group Menu.CATEGORY_ALTERNATIVE, //item id Menu.CATEGORY_ALTERNATIVE, //item order this.getComponentName(), //our activity class name null, //Specific menu items to place first launch, // the intent to handle 0, //no special flags to control menu items null); //Optional array in which to place the menu return true; } Dialogs Analogous to Java's JOptionPane • Functionality: Popup windows for user interaction – Asynchronous: Returns immediately from the dialog call – Modal: The dialog gets focus while the dialog popup shows – Call Back Listeners: Required to receive user inputs – Layout: Dialogs can have a layout with subcomponents • Examples – Alerts: Simple output messages – Prompts: Accept user input – Toast: Alerts that disappear after a designated time period Alerts if (validate(field1) == false) { showAlert("Very Bad"); } public static void showAlert(String message, Context ctx) { AlertDialog.Builder builder = new AlertDialog.Builder(ctx); //Create a builder builder.setTitle("Alert Window"); // Configure the anonymous listener builder.setPositiveButton("OK", new OnClickListener() { public void onClick(DialogInterface v, int buttonId) {} } ); AlertDialog alert = builder.create(); // Create the dialog alert.show(); // Make it visible } Prompts • Create a layout for a prompt dialog: using xml in res/layout • Create a builder object AlertDialog.Builder builder = new AlertDialog.Builder(context); Builder.setTitle("Why this?"); • Set the layout as the builder view LayoutInflater promptLayout = LayoutInflater.from(activity); View view = promptLayout.inflate(R.layout.prompt, null); builder.setView(view); • Add buttons and callbacks PromptListener listener = new PromptListener(view); // User-defined class Builder.setPositiveButton("OK", listener); Builder.setNegativeButton("Cancel", listener); • Create and show the dialog: AlertDialog ad = builder.create(); ad.show(); Note: For applications with many dialogs, Android provides a Managed-Dialog factory scheme for reusing previously created dialog objects Toast An alert that displays for a period of time, and then disappears • Toast display (could be a useful debug tool) public void toastDisplay(String message) { String data = "MY_CLASS" + ":" + message; Toast toast = Toast.makeText (activity, data, Toast.LENGTH_SHORT); // user definable Toast.show(); } • Exercise the toast display function toastDisplay("hello"); toastDisplay(resources.getString(R.string.toast_msg);