4.3 Menu and Pickers
Task 1: Add items to the options menu
- 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.) - 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. - 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
.
- 2 Add more menu items to the options menu
- 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 Settingschoice), which is defined as - Change the following attributes of the
action_settings
item to make it theaction_contact
item (don't change the existingandroid:orderInCategory
attribute)
- 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
- Extract the hard-coded string
"Order"
into the string resourceaction_order
.
- Add two more menu items the same way with the following attributes.
- 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.
- Open MainActivity, and change the
if
statement in theonOptionsItemSelected()
method replacing the idaction_settings
with the new idaction_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.
Task 2: Add icons for menu items
2.1 Add icons for menu items
- 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
- 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.
- Run the app. You should now see at least two icons in the app bar: the icon for Orderand the icon for Status as shown on the left side of the figure below. (The Favoritesand 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.
Task 3: Handle the selected menu item
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
- ind 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
- 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.
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 theaction_order
case to the following, which startOrderActivity
(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 4: Use a dialog to request a user’s choice
4.1 Create a new app to show an alert dialog
- 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.
4.2 Add an alert dialog to the main activity
- Open MainActivity and add the beginning of the
onClickShowAlert()
method
- Add the code to set the title and the message for the alert dialog to
onClickShowAlert()
after the comment
- 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.
- 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
Task 5: Use a picker for user input
5.1 Create a new app to show a 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"
5.2 Create a new 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;
- 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
- 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
- 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);
- 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);
}
- Run the app. After selecting the date, the date appears in a
Toast
message as shown on the right side of the following figure.