1. Welcome
Introduction
The app bar (also called the action bar) is a dedicated space at the top of each activity screen. When you create an Activity
from the Basic Activity template, Android Studio includes an app bar.
The options menu in the app bar usually provides choices for navigation, such as navigation to another activity in the app. The menu might also provide choices that affect the use of the app itself, for example ways to change settings or profile information, which usually happens in a separate activity.
In this practical you learn about setting up the app bar and options menu in your app, as shown in the figure below.
In the figure above:
- App bar. The app bar includes the app title, the options menu, and the overflow button.
- Options menu action icons. The first two options menu items appear as icons in the app bar.
- Overflow button. The overflow button (three vertical dots) opens a menu that shows more options menu items.
- Options overflow menu. After clicking the overflow button, more options menu items appear in the overflow menu.
Options menu items appear in the options overflow menu (see figure above). However, you can place some items as icons—as many as can fit—in the app bar. Using the app bar for the options menu makes your app consistent with other Android apps, allowing users to quickly understand how to operate your app and have a great experience.
You also create an app that shows a dialog to request a user's choice, such as an alert that requires users to tap OK or Cancel. A dialog is a window that appears on top of the display or fills the display, interrupting the flow of activity. Android provides ready-to-use dialogs, called pickers, for picking a time or a date. You can use them to ensure that your users pick a valid time or date that is formatted correctly and adjusted to the user's local time and date. In this lesson you'll also create an app with the date picker.
What you should already know
You should be able to:
- Create and run apps in Android Studio.
- Create and edit UI elements using the layout editor.
- Edit XML layout code, and access elements from your Java code.
- Add a click handler to a
Button
.
What you'll learn
- How to add menu items to the options menu.
- How to add icons for items in the options menu.
- How to set menu items to show in the app bar.
- How to add click handlers for menu items.
- How to add a dialog for an alert.
- How to add the date picker.
What you'll do
- Continue adding features to the Droid Cafe project from the previous practical.
- Add menu items to the options menu.
- Add icons for menu items to appear in the app bar.
- Connect menu-item clicks to event handlers that process the click events.
- Use an alert dialog to request a user's choice.
- Use a date picker for date input.
2. App overview
In the previous practical you created an app called Droid Cafe, shown in the figure below, using the Basic Activity template. This template also provides a skeletal options menu in the app bar at the top of the screen.
For this exercise you are using the v7 appcompat support library's Toolbar
as an app bar, which works on the widest range of devices and also gives you room to customize your app bar later on as your app develops. To read more about design considerations for using the app bar, see Responsive layout grid in the Material Design specification.
You create a new app that displays an alert dialog. The dialog interrupts the user's workflow and requires the user to make a choice.
You also create an app that provides a Button
to show the date picker, and converts the chosen date to a string to show in a Toast
message.
3. Task 1: Add items to the options menu
In this task you open the DroidCafeInput project from the previous practical and add menu items to the options menu in the app bar at the top of the screen.
1.1 Examine the code
Open the DroidCafeInput app from the practical on using input controls and examine the following layout files in the res > layout folder:
- activity_main.xml: The main layout for
MainActivity
, the first screen the user sees. - content_main.xml: The layout for the content of the
MainActivity
screen, which (as you will see shortly) is included within activity_main.xml. - activity_order.xml: The layout for
OrderActivity
, which you added in the practical on using input controls.
Follow these steps:
- Open content_main.xml and click the Text tab to see the XML code. The
app:layout_behavior
for theConstraintLayout
is set to@string/appbar_scrolling_view_behavior
, which controls how the screen scrolls in relation to the app bar at the top. (This string resource is defined in a generated file calledvalues.xml
, which you should not edit.)
For more about scrolling behavior, see Android Design Support Library in the Android Developers Blog. For design practices involving scrolling menus, see Scrolling in the Material Design specification.
- Open activity_main.xml and click the Text tab to see the XML code for the main layout, which uses a
CoordinatorLayout
layout with an embeddedAppBarLayout
layout. TheCoordinatorLayout
and theAppBarLayout
tags require fully qualified names that specifyandroid.support.design
, which is the Android Design Support Library.
AppBarLayout
is like a vertical LinearLayout
. It uses the Toolbar
class in the support library, instead of the native ActionBar
, to implement an app bar. The Toolbar
within this layout has the id toolbar
, and is also specified, like the AppBarLayout
, with a fully qualified name (android.support.v7.widget
).
The app bar is a section at the top of the display that can display the activity title, navigation, and other interactive items. The native ActionBar
behaves differently depending on the version of Android running on the device. For this reason, if you are adding an options menu, you should use the v7 appcompat support library's Toolbar
as an app bar. Using the Toolbar
makes it easy to set up an app bar that works on the widest range of devices, and also gives you room to customize your app bar later on as your app develops. Toolbar
includes the most recent features, and works for any device that can use the support library.
The activity_main.xml layout also uses an include layout
statement to include the entire layout defined in content_main.xml. This separation of layout definitions makes it easier to change the layout's content apart from the layout's toolbar definition and coordinator layout. This is a best practice for separating your content (which may need to be translated) from the format of your layout.
- Run the app. Notice the bar at the top of the screen showing the name of the app (Droid Cafe). It also shows the action overflow button (three vertical dots) on the right side. Tap the overflow button to see the options menu, which at this point has only one menu option, Settings.
- Examine the AndroidManifest.xml file. The
.MainActivity
activity is set to use theNoActionBar
theme. This theme is defined in thestyles.xml
file (open app > res >values > styles.xml to see it). Styles are covered in another lesson, but you can see that theNoActionBar
theme sets thewindowActionBar
attribute tofalse
(no window app bar), and thewindowNoTitle
attribute totrue
(no title). These values are set because you are defining the app bar withAppBarLayout
, rather than using anActionBar
. Using one of theNoActionBar
themes prevents the app from using the nativeActionBar
class to provide the app bar. - Look at MainActivity, which extends
AppCompatActivity
and starts with theonCreate()
method, which sets the content view to theactivity_main.xml
layout and setstoolbar
to be theToolbar
defined in the layout. It then callssetSupportActionBar()
and passestoolbar
to it, setting thetoolbar
as the app bar for theActivity
.
For best practices about adding the app bar to your app, see Add the app bar.
1.2 Add more menu items to the options menu
You will add the following menu items to the options menu:
- Order: Navigate to
OrderActivity
to see the dessert order. - Status: Check the status of an order.
- Favorites: Show favorite desserts.
- Contact: Contact the cafe. Because you don't need the existing Settings item, you will change Settings to Contact.
Android provides a standard XML format to define menu items. Instead of building a menu in your Activity
code, you can define a menu and all of its menu items in an XML menu resource. You can then inflate the menu resource (load it as a Menu
object) in your Activity
:
- Expand res > menu in the Project > Android pane, and open menu_main.xml. The only menu item provided from the template is
action_settings
(the Settings choice), which is defined as:
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
- Change the following attributes of the
action_settings
item to make it theaction_contact
item (don't change the existingandroid:orderInCategory
attribute):
Attribute | Value |
|
|
|
|
|
|
- Extract the hard-coded string
"Contact"
into the string resourceaction_contact
. - Add a new menu item using the
<item>
tag within the<menu>
block, and give the item the following attributes:
Attribute | Value |
|
|
|
|
|
|
|
|
The android:orderInCategory
attribute specifies the order in which the menu items appear in the menu, with the lowest number appearing higher in the menu. The Contact item is set to 100, which is a big number in order to specify that it shows up at the bottom rather than the top. You set the Order item to 10, which puts it above Contact, and leaves plenty of room in the menu for more items.
- Extract the hard-coded string
"Order"
into the string resourceaction_order
. - Add two more menu items the same way with the following attributes:
Status item attribute | Value |
|
|
|
|
|
|
|
|
Favorites item attribute | Value |
|
|
|
|
|
|
|
|
- Extract
"Status"
into the resourceaction_status
, and"Favorites"
into the resourceaction_favorites
. - You will display a
Toast
message with an action message depending on which menu item the user selects. Open strings.xml and add the following string names and values for these messages:
<string name="action_order_message">You selected Order.</string>
<string name="action_status_message">You selected Status.</string>
<string name="action_favorites_message">You selected Favorites.</string>
<string name="action_contact_message">You selected Contact.</string>
- Open MainActivity, and change the
if
statement in theonOptionsItemSelected()
method replacing the idaction_settings
with the new idaction_order
:
if (id == R.id.action_order)
Run the app, and tap the action overflow icon, shown on the left side of the figure below, to see the options menu, shown on the right side of the figure below. You will soon add callbacks to respond to items selected from this menu.
In the figure above:
- Tap the overflow icon in the app bar to see the options menu.
- The options menu drops down from the app bar.
Notice the order of items in the options menu. You used the android:orderInCategory
attribute to specify the priority of the menu items in the menu: The Order item is 10, followed by Status (20) and Favorites (30), and Contact is last (100). The following table shows the priority of items in the menu:
Menu item | orderInCategory attribute |
Order |
|
Status |
|
Favorites |
|
Contact |
|
4. Task 2: Add icons for menu items
Whenever possible, you want to show the most frequently used actions using icons in the app bar so the user can click them without having to first click the overflow icon. In this task, you add icons for some of the menu items, and show some of menu items in the app bar at the top of the screen as icons.
In this example, assume that the Order and Status actions are the most frequently used. The Favorites action is occasionally used, and Contact is the least frequently used. You can set icons for these actions and specify the following:
- Order and Status should always be shown in the app bar.
- Favorites should be shown in the app bar if it will fit; if not, it should appear in the overflow menu.
- Contact should not appear in the app bar; it should only appear in the overflow menu.
2.1 Add icons for menu items
To specify icons for actions, you need to first add the icons as image assets to the drawable folder using the same procedure you used in the practical on using clickable images. You want to use the following icons (or similar ones):
Order: Use the same icon you added for the floating action button in the practical on using clickable images (ic_shopping_cart.png).
Status:
Favorites:
- Contact: No need for an icon because it will appear only in the overflow menu.
For the Status and Favorites icons, follow these steps:
- Expand res in the Project > Android pane, and right-click (or Control-click) the drawable folder.
- Choose New > Image Asset. The Configure Image Asset dialog appears.
- Choose Action Bar and Tab Items in the drop-down menu.
- Change ic_action_name to another name (such as ic_status_info for the Status icon).
- Click the clip art image (the Android logo next to Clipart:) to select a clip art image as the icon. A page of icons appears. Click the icon you want to use.
- Choose HOLO_DARK from the Theme drop-down menu. This sets the icon to be white against a dark-colored (or black) background. Click Next and then click Finish.
2.2 Show the menu items as icons in the app bar
To show menu items as icons in the app bar, use the app:showAsAction
attribute in menu_main.xml
. The following values for the attribute specify whether or not the action should appear in the app bar as an icon:
"always"
: Always appears in the app bar. (If there isn't enough room it may overlap with other menu icons.)"ifRoom"
: Appears in the app bar if there is room."never"
: Never appears in the app bar; its text appears in the overflow menu.
Follow these steps to show some of the menu items as icons:
- Open menu_main.xml again, and add the following attributes to the Order, Status, and Favorites items so that the first two (Order and Status) always appear, and the Favorites item appears only if there is room for it:
Order item attribute | Old value | New value |
| none |
|
|
|
|
Status item attribute | Old value | New value |
| none |
|
|
|
|
Favorites item attribute | Old value | New value |
| none |
|
|
|
|
- Run the app. You should now see at least two icons in the app bar: the icon for Order and the icon for Status as shown on the left side of the figure below. (The Favorites and Contact options appear in the overflow menu.)
- Rotate your device to the horizontal orientation, or if you're running in the emulator, click the Rotate Left or Rotate Right icons to rotate the display into the horizontal orientation. You should then see all three icons in the app bar for Order, Status, and Favorites as shown on the right side of the figure below.
How many action buttons will fit in the app bar? It depends on the orientation and the size of the device screen. Fewer buttons appear in a vertical orientation, as shown on the left side of the figure above, compared to a horizontal orientation as shown on the right side of the figure above. Action buttons may not occupy more than half of the main app bar width.
5. Task 3: Handle the selected menu item
In this task, you add a method to display a message about which menu item is tapped, and use the onOptionsItemSelected()
method to determine which menu item was tapped.
3.1 Create a method to display the menu choice
- Open MainActivity.
- If you haven't already added the following method (in another lesson) for displaying a
Toast
message, add it now. You will use it as the action to take for each menu choice. (Normally you would implement an action for each menu item such as starting anotherActivity
, as shown later in this lesson.)
public void displayToast(String message) {
Toast.makeText(getApplicationContext(), message,
Toast.LENGTH_SHORT).show();
}
3.2 Use the onOptionsItemSelected event handler
The onOptionsItemSelected()
method handles selections from the options menu. You will add a switch case
block to determine which menu item was selected and what action to take.
- Find the
onOptionsItemSelected()
method provided by the template. The method determines whether a certain menu item was clicked, using the menu item'sid
. In the example below, theid
isaction_order
:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_order) {
return true;
}
return super.onOptionsItemSelected(item);
}
- Replace the
int id
assignment statement and theif
statement with the followingswitch case
block, which sets the appropriatemessage
based on the menu item'sid
:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_order:
displayToast(getString(R.string.action_order_message));
return true;
case R.id.action_status:
displayToast(getString(R.string.action_status_message));
return true;
case R.id.action_favorites:
displayToast(getString(R.string.action_favorites_message));
return true;
case R.id.action_contact:
displayToast(getString(R.string.action_contact_message));
return true;
default:
// Do nothing
}
return super.onOptionsItemSelected(item);
}
- Run the app. You should now see a different
Toast
message on the screen, as shown on the right side of the figure below, based on which menu item you choose.
In the figure above:
- Selecting the Contact item in the options menu.
- The
Toast
message that appears.
3.3 Start an Activity from a menu item
Normally you would implement an action for each menu item, such as starting another Activity
. Referring the snippet from the previous task, change the code for the action_order
case to the following, which starts OrderActivity
(using the same code you used for the floating action button in the lesson on using clickable images):
switch (item.getItemId()) {
case R.id.action_order:
Intent intent = new Intent(MainActivity.this, OrderActivity.class);
intent.putExtra(EXTRA_MESSAGE, mOrderMessage);
startActivity(intent);
return true;
// ... code for other cases
}
Run the app. Clicking the shopping cart icon in the app bar (the Order item) takes you directly to the OrderActivity
screen.
Task 3 solution code
Android Studio project: DroidCafeOptions
6. Coding challenge
Challenge: A context menu allows users to take an action on a selected View
. While the options menu in the app bar usually provides choices for navigation to another activity, you use a context menu to allow the user to modify a View
within the current activity.
Both menus are described in XML, both are inflated using MenuInflater
, and both use an "on item selected" method—in this case, onContextItemSelected()
. So the techniques for building and using the two menus are similar.
A context menu appears as a floating list of menu items when the user performs a touch & hold on a View
, as shown in the left side of the figure below. For this challenge, add a context menu to the ScrollingText app to show three options: Edit, Share, and Delete, as shown in the figure below. The menu appears when the user performs a touch & hold on the TextView
. The app then displays a Toast
message showing the menu option chosen, as shown in the right side of the figure.
Hints
A context menu is similar to the options menu, with two critical differences:
- The context menu must be registered to a
View
so that the menu inflates when a touch & hold occurs on theView
. - Although the options menu code is supplied by the Basic Activity template, for a context menu you have to add the code and menu resource yourself.
To solve this challenge, follow these general steps:
- Create an XML menu resource file for the menu items.
Right-click the res folder and choose New > Android Resource Directory. Choose menu in the Resource type drop-down menu and click OK. Then right-click the new menu folder, choose New > Menu resource file, enter the name menu_context, and click OK. Open menu_context and enter the menu items as you did for an options menu.
- Register the
View
to the context menu using theregisterForContextMenu()
method.
In the onCreate()
method, register the TextView
:
TextView article_text = findViewById(R.id.article);
registerForContextMenu(article_text);
- Implement the
onCreateContextMenu()
method in theActivity
to inflate the menu.
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_context, menu);
}
- Implement the
onContextItemSelected()
method in theActivity
to handle menu-item clicks. In this case, simply display aToast
with the menu choice.
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.context_edit:
displayToast("Edit choice clicked.");
return true;
case R.id.context_share:
displayToast("Share choice clicked.");
return true;
case R.id.context_delete:
displayToast("Delete choice clicked.");
return true;
default:
return super.onContextItemSelected(item);
}
}
- Run the app. If you tap and drag, the text scrolls as before. However, if you do a long tap, the contextual menu appears.
Challenge solution code
Android Studio project: ContextMenuScrollingText
7. Task 4: Use a dialog to request a user's choice
You can provide a dialog to request a user's choice, such as an alert that requires users to tap OK or Cancel. A dialog is a window that appears on top of the display or fills the display, interrupting the flow of activity.
For example, an alert dialog might require the user to click Continue after reading it, or give the user a choice to agree with an action by clicking a positive button (such as OK or Accept), or to disagree by clicking a negative button (such as Cancel). Use the AlertDialog
subclass of the Dialog
class to show a standard dialog for an alert.
In this practical, you use a Button
to trigger a standard alert dialog. In a real-world app, you might trigger an alert dialog based on some condition, or based on the user tapping something.
4.1 Create a new app to show an alert dialog
In this exercise, you build an alert with OK and Cancel buttons. The alert is triggered by the user tapping a button.
- Create a new project called Dialog For Alert based on the Empty Activity template.
- Open the activity_main.xml layout file to show the layout editor.
- Edit the
TextView
element to say Hello World! Tap to test the alert: instead of "Hello World!" - Add a
Button
under theTextView
. (Optional: Constrain the button to the bottom of theTextView
and the sides of the layout, with margins set to 8dp.) - Set the text of the
Button
to Alert. - Switch to the Text tab, and extract the text strings for the
TextView
andButton
to string resources. - Add the
android:onClick
attribute to the button to call the click handleronClickShowAlert()
. After you enter it, the click handler is underlined in red because it has not yet been created.
android:onClick="onClickShowAlert"
You now have a layout similar to the following:
4.2 Add an alert dialog to the main activity
The builder design pattern makes it easy to create an object from a class that has a lot of required and optional attributes and would therefore require a lot of parameters to build. Without this pattern, you would have to create constructors for combinations of required and optional attributes; with this pattern, the code is easier to read and maintain. For more information about the builder design pattern, see Builder pattern.
The builder class is usually a static member class of the class it builds. Use AlertDialog.Builder
to build a standard alert dialog, with setTitle()
to set its title, setMessage()
to set its message, and setPositiveButton()
and setNegativeButton()
to set its buttons.
To make the alert, you need to make an object of AlertDialog.Builder
. You will add the onClickShowAlert()
click handler for the Alert Button
, which makes this object as its first order of business. That means that the dialog will be created only when the user clicks the Alert Button
. While this coding pattern is logical for using a Button
to test an alert, for other apps you may want to create the dialog in the onCreate()
method so that it is always available for other code to trigger it.
- Open MainActivity and add the beginning of the
onClickShowAlert()
method:
public void onClickShowAlert(View view) {
AlertDialog.Builder myAlertBuilder = new
AlertDialog.Builder(MainActivity.this);
// Set the dialog title and message.
}
If AlertDialog.Builder
is not recognized as you enter it, click the red light bulb icon, and choose the support library version (android.support.v7.app.AlertDialog) for importing into your Activity
.
- Add the code to set the title and the message for the alert dialog to
onClickShowAlert()
after the comment:
// Set the dialog title and message.
myAlertBuilder.setTitle("Alert");
myAlertBuilder.setMessage("Click OK to continue, or Cancel to stop:");
// Add the dialog buttons.
- Extract the strings above to string resources as
alert_title
andalert_message
. - Add the OK and Cancel buttons to the alert with
setPositiveButton()
andsetNegativeButton()
methods:
// Add the dialog buttons.
myAlertBuilder.setPositiveButton("OK", new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// User clicked the OK button.
Toast.makeText(getApplicationContext(), "Pressed OK",
Toast.LENGTH_SHORT).show();
}
});
myAlertBuilder.setNegativeButton("Cancel", new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// User cancelled the dialog.
Toast.makeText(getApplicationContext(), "Pressed Cancel",
Toast.LENGTH_SHORT).show();
}
});
// Create and show the AlertDialog.
After the user taps the OK or Cancel button in the alert, you can grab the user's selection and use it in your code. In this example, you display a Toast
message.
- Extract the strings for OK and Cancel to string resources as
ok_button
andcancel_button
, and extract the strings for theToast
messages. - At the end of the
onClickShowAlert()
method, addshow()
, which creates and then displays the alert dialog:
// Create and show the AlertDialog.
myAlertBuilder.show();
- Run the app.
You should be able to tap the Alert button, shown on the left side of the figure below, to see the alert dialog, shown in the center of the figure below. The dialog shows OK and Cancel buttons, and a Toast
message appears showing which one you pressed, as shown on the right side of the figure below.
Task 4 solution code
Android Studio project: DialogForAlert
8. Task 5: Use a picker for user input
Android provides ready-to-use dialogs, called pickers, for picking a time or a date. You can use them to ensure that your users pick a valid time or date that is formatted correctly and adjusted to the user's local time and date. Each picker provides controls for selecting each part of the time (hour, minute, AM/PM) or date (month, day, year). You can read all about setting up pickers in Pickers.
In this task you'll create a new project and add the date picker. You will also learn how to use a Fragment
, which is a behavior or a portion of a UI within an Activity
. It's like a mini-Activity
within the main Activity
, with its own lifecycle, and it's used for building a picker. All the work is done for you. To learn about the Fragment
class, see Fragments in the API Guide.
One benefit of using a Fragment
for a picker is that you can isolate the code sections for managing the date and the time for various locales that display date and time in different ways. The best practice to show a picker is to use an instance of DialogFragment
, which is a subclass of Fragment
. A DialogFragment
displays a dialog window floating on top of the Activity
window. In this exercise, you'll add a Fragment
for the picker dialog and use DialogFragment
to manage the dialog lifecycle.
5.1 Create a new app to show a date picker
To start this task, create an app that provides a Button
to show the date picker.
- Create a new project called Picker For Date based on the Empty Activity template.
- Open the activity_main.xml layout file to show the layout editor.
- Edit the
TextView
element's "Hello World!" text to Hello World! Choose a date:. - Add a
Button
underneath theTextView
. (Optional: Constrain theButton
to the bottom of theTextView
and the sides of the layout, with margins set to 8dp.) - Set the text of the
Button
to Date. - Switch to the Text tab, and extract the strings for the
TextView
andButton
to string resources. - Add the
android:onClick
attribute to theButton
to call the click handlershowDatePicker()
. After entering it, the click handler is underlined in red because it has not yet been created.
android:onClick="showDatePicker"
You should now have a layout similar to the following:
5.2 Create a new fragment for the date picker
In this step, you add a Fragment
for the date picker.
- Expand app > java > com.example.android.pickerfordate and select MainActivity.
- Choose File > New > Fragment > Fragment (Blank), and name the fragment DatePickerFragment. Clear all three checkboxes so that you don't create a layout XML, include fragment factory methods, or include interface callbacks. You don't need to create a layout for a standard picker. Click Finish.
- Open DatePickerFragment and edit the
DatePickerFragment
class definition to extendDialogFragment
and implementDatePickerDialog.OnDateSetListener
to create a standard date picker with a listener. See Pickers for more information about extendingDialogFragment
for a date picker:
public class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener {
As you enter DialogFragment and DatePickerDialog.OnDateSetListener, Android Studio automatically adds several import
statements to the import
block at the top, including:
import android.app.DatePickerDialog;
import android.support.v4.app.DialogFragment;
In addition, a red bulb icon appears in the left margin after a few seconds.
- Click the red bulb icon and choose Implement methods from the popup menu. A dialog appears with
onDateSet()
already selected and the Insert @Override option selected. Click OK to create the emptyonDateSet()
method. This method will be called when the user sets the date.
After adding the empty onDateSet()
method, Android Studio automatically adds the following in the import
block at the top:
import android.widget.DatePicker;
The onDateSet()
parameters should be int i
, int i1
, and int i2
. Change the names of these parameters to ones that are more readable:
public void onDateSet(DatePicker datePicker,
int year, int month, int day)
- Remove the empty
public DatePickerFragment()
public constructor. - Replace the entire
onCreateView()
method withonCreateDialog()
that returnsDialog
, and annotateonCreateDialog()
with@NonNull
to indicate that thereturn
valueDialog
can't be null. Android Studio displays a red bulb next to the method because it doesn'treturn
anything yet.
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
}
- Add the following code to
onCreateDialog()
to initialize theyear
,month
, andday
fromCalendar
, and return the dialog and these values to theActivity
. As you enter Calendar.getInstance(), specify the import to be java.util.Calendar.
// Use the current date as the default date in the picker.
final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
// Create a new instance of DatePickerDialog and return it.
return new DatePickerDialog(getActivity(), this, year, month, day);
5.4 Modify the main activity
While much of the code in MainActivity.java
stays the same, you need to add a method that creates an instance of FragmentManager
to manage the Fragment
and show the date picker.
- Open MainActivity.
- Add the
showDatePickerDialog()
handler for the DateButton
. It creates an instance ofFragmentManager
usinggetSupportFragmentManager()
to manage theFragment
automatically, and to show the picker. For more information about theFragment
class, see Fragments.
public void showDatePicker(View view) {
DialogFragment newFragment = new DatePickerFragment();
newFragment.show(getSupportFragmentManager(),"datePicker");
}
- Extract the string
"datePicker"
to the string resourcedatepicker
. - Run the app. You should see the date picker after tapping the Date button.
5.5 Use the chosen date
In this step you pass the date back to MainActivity.java
, and convert the date to a string that you can show in a Toast
message.
- Open MainActivity and add an empty
processDatePickerResult()
method that takes theyear
,month
, andday
as arguments:
public void processDatePickerResult(int year, int month, int day) {
}
- Add the following code to the
processDatePickerResult()
method to convert themonth
,day
, andyear
to separate strings, and to concatenate the three strings with slash marks for the U.S. date format:
String month_string = Integer.toString(month+1);
String day_string = Integer.toString(day);
String year_string = Integer.toString(year);
String dateMessage = (month_string +
"/" + day_string + "/" + year_string);
The month
integer returned by the date picker starts counting at 0 for January, so you need to add 1 to it to show months starting at 1.
- Add the following after the code above to display a
Toast
message:
Toast.makeText(this, "Date: " + dateMessage,
Toast.LENGTH_SHORT).show();
- Extract the hard-coded string
"Date: "
into a string resource nameddate
. - Open DatePickerFragment, and add the following to the
onDateSet()
method to invokeprocessDatePickerResult()
inMainActivity
and pass it theyear
,month
, andday
:
@Override
public void onDateSet(DatePicker datePicker,
int year, int month, int day) {
MainActivity activity = (MainActivity) getActivity();
activity.processDatePickerResult(year, month, day);
}
You use getActivity()
which, when used in a Fragment
, returns the Activity
the Fragment
is currently associated with. You need this because you can't call a method in MainActivity
without the context of MainActivity
(you would have to use an intent
instead, as you learned in another lesson). The Activity
inherits the context, so you can use it as the context for calling the method (as in activity.processDatePickerResult
).
- Run the app. After selecting the date, the date appears in a
Toast
message as shown on the right side of the following figure.
Task 5 solution code
Android Studio project: PickerForDate
9. Coding challenge 2
Challenge: Create an app called Picker For Time that implements the time picker using the same technique you just learned for adding a date picker.
Hints:
- Implement
TimePickerDialog.OnTimeSetListener
to create a standard time picker with a listener. - Change the
onTimeSet()
method's parameters fromint i
toint hourOfDay
andint i1
toint minute
. - Get the current hour and minute from
Calendar
:
final Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
- Create a
processTimePickerResult()
method similar toprocessDatePickerResult()
in the previous task that converts the time elements to strings and displays the result in aToast
message.
Run the app, and click the Time button as shown in the left side of the figure below. The time picker should appear, as shown in the center of the figure. Choose a time and click OK. The time should appear in a Toast message at the bottom of the screen, as shown in the right side of the figure.
Challenge 2 solution code
Android Studio project: PickerForTime
10. Summary
Provide an options menu and app bar:
- Start your app or
Activity
with the Basic Activity template to automatically set up the app bar, the options menu, and a floating action button. - The template sets up a
CoordinatorLayout
layout with an embeddedAppBarLayout
layout.AppBarLayout
is like a verticalLinearLayout
. It uses theToolbar
class in the support library, instead of the nativeActionBar
, to implement an app bar. - The template modifies the
AndroidManifest.xml
file so that the.MainActivity
Activity
is set to use theNoActionBar
theme. This theme is defined in thestyles.xml
file. - The template sets
MainActivity
to extendAppCompatActivity
and starts with theonCreate()
method, which sets the content view andToolbar
. It then callssetSupportActionBar()
and passestoolbar
to it, setting thetoolbar
as the app bar for theActivity
. - Define menu items in the
menu_main.xml
file. Theandroid:orderInCategory
attribute specifies the order in which the menu items appear in the menu, with the lowest number appearing higher in the menu. - Use the
onOptionsItemSelected()
method to determine which menu item was tapped.
Add an icon for an options menu item:
- Expand res in the Project > Android pane, and right-click (or Control-click) the drawable folder. Choose New > Image Asset.
- Choose Action Bar and Tab Items in the drop-down menu, and change the name of the image file.
- Click the clip art image to select a clip art image as the icon. Choose an icon.
- Choose HOLO_DARK from the Theme drop-down menu.
Show menu items as icons in the app bar:
- Use the
app:showAsAction
attribute inmenu_main.xml
with the following values. "always"
: Always appears in the app bar. (If there isn't enough room it may overlap with other menu icons.)"ifRoom"
: Appears in the app bar if there is room."never"
: Never appears in the app bar; its text appears in the overflow menu.
Use an alert dialog:
- Use a dialog to request a user's choice, such as an alert that requires users to tap OK or Cancel. Use dialogs sparingly as they interrupt the user's workflow.
- Use the
AlertDialog
subclass of theDialog
class to show a standard dialog for an alert. - Use
AlertDialog.Builder
to build a standard alert dialog, withsetTitle()
to set its title,setMessage()
to set its message, andsetPositiveButton()
andsetNegativeButton()
to set its buttons.
Use a picker for user input:
- Use
DialogFragment
, a subclass ofFragment
, to build a picker such as the date picker or time picker. - Create a
DialogFragment
, and implementDatePickerDialog.OnDateSetListener
to create a standard date picker with a listener. IncludeonDateSet()
in thisFragment
. - Replace the
onCreateView()
method withonCreateDialog()
that returnsDialog
. Initialize the date for the date picker fromCalendar
, and return the dialog and these values to theActivity
. - Create an instance of
FragmentManager
usinggetSupportFragmentManager()
to manage theFragment
and show the date picker.
11. Related concept
The related concept documentation is in 4.3: Menus and pickers.
12. Learn more
Android Studio documentation:
Android developer documentation:
- Add the app bar
- Menus
Toolbar
- v7 appcompat support library
AppBarLayout
onOptionsItemSelected()
View
MenuInflater
registerForContextMenu()
onCreateContextMenu()
onContextItemSelected()
- Dialogs
AlertDialog
- Pickers
- Fragments
DialogFragment
FragmentManager
Calendar
Material Design spec:
Other:
- Android Developers Blog: Android Design Support Library
- Builder pattern in Wikipedia
13. Homework
This section lists possible homework assignments for students who are working through this codelab as part of a course led by an instructor. It's up to the instructor to do the following:
- Assign homework if required.
- Communicate to students how to submit homework assignments.
- Grade the homework assignments.
Instructors can use these suggestions as little or as much as they want, and should feel free to assign any other homework they feel is appropriate.
If you're working through this codelab on your own, feel free to use these homework assignments to test your knowledge.
Build and run an app
Open the DroidCafeOptions app that you created in this lesson.
- Add a Date button under the delivery options that shows the date picker.
- Show the user's chosen date in a
Toast
message.
Answer these questions
Question 1
What is the name of the file in which you create options menu items? Choose one:
- menu.java
- menu_main.xml
- activity_main.xml
- content_main.xml
Question 2
Which method is called when an options menu item is clicked? Choose one:
onOptionsItemSelected(MenuItem item)
onClick(View view)
onContextItemSelected()
onClickShowAlert()
Question 3
Which of the following statements sets the title for an alert dialog? Choose one:
myAlertBuilder.setMessage("Alert");
myAlertBuilder.setPositiveButton("Alert");
myAlertBuilder.setTitle("Alert");
AlertDialog.Builder myAlertBuilder = new AlertDialog.Builder("Alert");
Question 4
Where do you create a DialogFragment
for a date picker? Choose one:
- In the
onCreate()
method in the hostingActivity
. - In the
onCreateContextMenu()
method inFragment
. - In the
onCreateView()
method in the extension ofDialogFragment
. - In the
onCreateDialog()
method in the extension ofDialogFragment
.
Submit your app for grading
Guidance for graders
Check that the app has the following features:
- The date picker is added as a
DialogFragment
. - Clicking the Date button (refer to the left side of the figure below) in
OrderActivity
shows the date picker (refer to the center of the figure). - Clicking the OK button in the date picker shows a
Toast
message inOrderActivity
with the chosen date (refer to the right side of the figure).
14. Next codelab
To find the next practical codelab in the Android Developer Fundamentals (V2) course, see Codelabs for Android Developer Fundamentals (V2).
For an overview of the course, including links to the concept chapters, apps, and slides, see Android Developer Fundamentals (Version 2).