This practical codelab is part of Unit 4: User experience in Mobile Development module. You will get the most value out of this course if you work through the codelabs in sequence:
For the complete list of codelabs in the course, see Blackboard.
For links to all the concept chapters, apps, and slides, see Android Developer Fundamentals (Version 2).
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:
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.
You should be able to:
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 androidx.appcompat.widget.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. A Toolbar is a generalization of action bars for use within application layouts. 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.
In this task you open the DroidCafeInput project from the previous practical (get a new copy from Blackboard) and add menu items to the options menu in the app bar at the top of the screen.
Open the DroidCafeInput app from the practical on using input controls and examine the following layout files in the res > layout folder:
MainActivity
, the layout components defined in this class are the AppBarLayout
which contains the Toolbar
and the FloatingActionButton
.NavHostFragment
controlling the navigation between the fragments, which (as you will see shortly) is included within activity_main.xml
.OrderFragment
, which you added in the practical on using input controls.Follow these steps:
app:layout_behavior
for the ConstraintLayout
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 called values.xml, which you should not edit.)CoordinatorLayout
and the AppBarLayout
tags require fully qualified names that specify androidx.coordinatorlayout.widget
and com.google.android.material.appbar
.AppBarLayout
is like a vertical LinearLayout
. It uses the Toolbar class in the appcompat 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 (androidx.appcompat.widget
).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 androidx appcompat widget 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.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..MainActivity
activity is set to use the NoActionBar
theme. This theme is defined in the styles.xml
file (open app > res > values > styles.xml to see it). Styles are covered in another lesson, but you can see that the NoActionBar
theme sets the windowActionBar
attribute to false
(no window app bar), and the windowNoTitle
attribute to true
(no title). These values are set because you are defining the app bar with AppBarLayout
, rather than using an ActionBar
. Using one of the NoActionBar
themes prevents the app from using the native ActionBar
class to provide the app bar.AppCompatActivity
and starts with the onCreate()
method, which sets the content view to the activity_main.xml
layout and sets toolbar
to be the Toolbar
defined in the layout. It then calls setSupportActionBar() and passes toolbar
to it, setting the toolbar
as the app bar for the Activity
.For best practices about adding the app bar to your app, see Add the app bar (not updated for androidx).
You will add the following menu items to the options menu:
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
:
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" />
action_settings
item to make it the action_contact
item (don't change the existing android:orderInCategory
attribute):Attribute | Value |
|
|
|
|
|
|
"Contact"
into the string resource action_contact
.Attribute | Value |
|
|
|
|
|
|
|
|
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."Order"
into the string resource action_order
.Status item attribute | Value |
|
|
|
|
|
|
|
|
Favorites item attribute | Value |
|
|
|
|
|
|
|
|
"Status"
into the resource action_status
, and "Favorites"
into the resource action_favorites
.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>
if
statement in the onOptionsItemSelected()
method replacing the id action_settings
with the new id action_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:
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 |
|
|
|
|
|
|
|
|
|
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:
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):
For the Status and Favorites icons, follow these steps:
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:
Order item attribute | Old value | New value |
| none |
|
|
|
|
Status item attribute | Old value | New value |
| none |
|
|
|
|
Favorites item attribute | Old value | New value |
| none |
|
|
|
|
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.
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.
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 displaying a different Fragment
, as shown later in this lesson.)public void displayToast(String message) {
Toast.makeText(getApplicationContext(), message,
Toast.LENGTH_SHORT).show();
}
onOptionsItemSelected
event handlerThe 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.
onOptionsItemSelected()
method provided by the template. The method determines whether a certain menu item was clicked, using the menu item's id
. In the example below, the id
is action_order
:@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_order) {
return true;
}
return super.onOptionsItemSelected(item);
}
int id
assignment statement and the if
statement with the following switch case
block, which sets the appropriate message
based on the menu item's id
:@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);
}
Toast
message on the screen depending on which menu item you choose.Normally you would implement an action for each menu item, such as displaying another Fragment
.
StatusFragment
and check that its android:id
is set to @+id/statusFragment
and set its android:label
to "Status Screen"
onOptionsItemSelected
from the previous task, change the code for the action_status
case to the following, which displays StatusFragment
(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_status:
navController.navigate(R.id.statusFragment);
return true;
// ... code for other cases
}
Run the app. Clicking the status icon in the app bar takes you directly to the StatusFragment
screen.The FloatingActionButton
(FAB) needs to be handled because it is managed by the Firstfragment
and will cause an error if we click it while the StatusFragment
is showing. In the next few steps we will hide the FAB.
public class StatusFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_status, container, false);
}
}
StatusFragment
hold a reference to the FAB:private FloatingActionButton fab;
StatusFragment
. The FAB itself has been created when the MainActivity
was started, and since all of our fragments exist inside the layout of the MainActivity
, we can obtain a reference to the FAB as soon as the StatusFragment
is attached. The sequence of lifecycle event callback functions in a fragment is; onAttach
, onCreate
, onCreateView
, onViewCreated
, onStart
, onResume
. After onResume
, the user can interact with the screen. We will get our reference to the FAB inside onCreateView
:@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
fab = getActivity().findViewById(R.id.fab);
return inflater.inflate(R.layout.fragment_status, container, false);
}
onCreateView
because we need to show the FAB again when the StatusFragment
is stopped and re-hidden if the user returns to the StatusFragment
. We need to ensure that our hide
/show
mechanism supports the user navigating to another APP and then returning to our APP while the StatusFragment
is being displayed. We will choose to hide the FAB in the onResume
method. Add this method to your StatusFragment
:@Override
public void onResume() {
super.onResume();
fab.hide();
}
FirstFragment
from the StatusFragment
, the FAB will remain hidden unless we show it again. As the StatusFragment
hid the FAB, it should also be responsible for restoring the FAB when StatusFragment
is closed. The options for when to restore the FAB to the screen are either in onPause
or in onStop
. If we restore the FAB in onPause
, the FAB will become visible in the case when the user clicks the button to show the list of running APPs on the device. Therefore the best place to restore the FAB is in the onStop
function:@Override
public void onStop() {
super.onStop();
fab.show();
}
StatusFragment
is displayed, but be restored when you navigate away and back to the FirstFragment
.The OrderFragment
also needs to control the FAB. Currently, clicking the FAB on the order screen will lead to an error because the handler is still managed by the FirstFragment
which is not currently active. Lets update the OrderFragment
in a similar way to the StatusFragment
. We will change the FAB icon to a shipping icon, display a Toast
as a placeholder for recording the order details, and then make it navigate back to the FirstFragment
.
ic_shipping
.OrderFragment
closes. Add the following two instance variables to your OrderFragment:private FloatingActionButton fab;
private Drawable fabIcon;
onViewCreated
method of your OrderFragment
. This will obtain the reference to the FAB, save a reference to the previous drawable (so we can restore it later), and replace the FAB icon with the ic_shipping
icon. We also provide an OnClickListener
which will simulate saving the order by displaying a Toast
, and then navigate back to the previous screen:fab = getActivity().findViewById(R.id.fab);
fabIcon = fab.getDrawable();
fab.setImageResource(R.drawable.ic_shipping);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(),"Order Delivery Saved", Toast.LENGTH_SHORT).show();
NavHostFragment.findNavController(OrderFragment.this).popBackStack();
}
});
onStop
method of the OrderFragment
:@Override
public void onStop() {
super.onStop();
fab.setImageDrawable(fabIcon);
}
OrderFragment
should display the ic_shipping
icon and clicking the FAB in the OrderFragment
should take you back to the FirstFragment
. We popped the navigation stack so the OnClickListener
for the FirstFragment
should be automatically restored.In this step you will make action_order
be handled differently when the FirstFragment
is displayed. The MainActivity
will check that the FirstFragment
is not displayed when handling action_order
. The result will be that when action_order
is invoked when FirstFragment
is displayed, the APP will to navigate to the OrderFragment
. Otherwise if FirstFragment
is not displayed, action_order
will be handled by MainActivity
and will cause the APP to navigate to FirstFragment
.
onOptionsItemSelected
to make the navigation to R.id.FirstFragment
be conditional on FirstFragment
not being displayed:public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_order:
if (navController.getCurrentDestination().getId() != R.id.FirstFragment) {
displayToast(getString(R.string.action_order_message));
navController.navigate(R.id.FirstFragment);
return true;
} else {
return super.onOptionsItemSelected(item);
}
// Other cases omitted
}
}
onCreate
method set that the fragment has an options menu:@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_order:
placeOrder();
return true;
default:
}
return super.onOptionsItemSelected(item);
}
private void placeOrder() {
FirstFragmentDirections.PlaceOrder action = FirstFragmentDirections.placeOrder();
if (mOrderMessage.length() > 0) {
action.setOrderText(mOrderMessage);
}
NavHostFragment.findNavController(FirstFragment.this)
.navigate(action);
}
OnClickListener
in FirstFragment.onViewCreated
to call placeOrder
and remove the duplicated code: fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
placeOrder();
}
});
action_order
(clicking the shopping trolley icon) on the action bar behaves differently depending on which fragment is currently displayed.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.
In this exercise, you build an alert with OK and Cancel buttons. The alert is triggered by the user tapping the FAB.
Button
in the FirstFragment
.Button
already has an onClick
handler attached:public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
}
If you run the APP you will see the following screen: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 NextButton
, which makes this object as its first order of business. That means that the dialog will be created only when the user clicks the NextButton
. 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.
navigate
code rather than delete it because we will need it as the action when the user clicks the OK button): public void onClick(View view) {
AlertDialog.Builder myAlertBuilder = new
AlertDialog.Builder(getContext());
// Set the dialog title and message.
//NavHostFragment.findNavController(FirstFragment.this)
// .navigate(R.id.action_FirstFragment_to_SecondFragment);
}
If AlertDialog.Builder
is not recognized as you enter it, click the red light bulb icon, and choose the androidx support library version (androidx.appcompat.app.AlertDialog
) for importing into your Fragment.onClick()
after the comment: public void onClick(View view) {
AlertDialog.Builder myAlertBuilder = new
AlertDialog.Builder(getContext());
// Set the dialog title and message.
myAlertBuilder.setTitle("Alert");
myAlertBuilder.setMessage("Click OK to continue, or Cancel to stop:");
// Add the dialog buttons.
//NavHostFragment.findNavController(FirstFragment.this)
// .navigate(R.id.action_FirstFragment_to_SecondFragment);
}
alert_title
and alert_message
.setPositiveButton()
and setNegativeButton()
methods: public void onClick(View view) {
AlertDialog.Builder myAlertBuilder = new
AlertDialog.Builder(getContext());
// Set the dialog title and message.
myAlertBuilder.setTitle(R.string.alert_title);
myAlertBuilder.setMessage(R.string.alert_message);
// Add the dialog buttons.
myAlertBuilder.setPositiveButton("OK", new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// User clicked OK button.
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
myAlertBuilder.setNegativeButton("Cancel", new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// User cancelled the dialog.
Toast.makeText(getContext(), "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 navigate to SecondFragment
(using the original navigate
code) when the user clicks the OK button, and display a Toast message when the user clicks Cancel.ok_button
and cancel_button
, and extract the string for the Toast
message.onClick()
method, add show()
, which creates and then displays the alert dialog:// Create and show the AlertDialog.
myAlertBuilder.show();
You should be able to tap the Next button, to see the alert dialog, shown in the figure below. The dialog shows OK and Cancel buttons. Clicking OK takes you to SecondFragment
and clicking Cancel causes a Toast
message to appear.
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.
To start this task, create an app that provides a Button
to show the date picker.
TextView
contains the text referred to by @string/hello_first_fragment
hello_first_fragment
to change its value from Hello first fragment
to Hello! Choose a date:Button
in fragment_first.xml
displays the text referred to by @string/next
<string name="date">Date</string>
android:text="@string/date"
In this step, you add a Fragment for the date picker.
DatePickerFragment
class definition to extend DialogFragment
and implement
DatePickerDialog.OnDateSetListener to create a standard date picker with a listener. Delete all of the automatically generated code inside the class. See Pickers for more information about extending DialogFragment
for a date picker:public class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener {
// to be completed...
}
As you enter DialogFragment
and DatePickerDialog.OnDateSetListener
, Android Studio automatically adds several import statements to the import block at the top. If DialogFragment
has more than one import option, make sure you import it from androidx.fragment.app.DialogFragment
. Your import statements should look like this:import android.app.DatePickerDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
In addition, a red bulb icon appears in the left margin after a few seconds.onDateSet()
method. This method will be called when the user sets the date.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)
Dialog
, and annotate onCreateDialog()
with @NonNull
to indicate that the return
value Dialog
can't be null
. Android Studio displays a red bulb next to the method because it doesn't return
anything yet.@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
}
onCreateDialog()
to initialize the year
, month
, and day
from Calendar, and return the dialog and these values to the Fragment
. As you enter Calendar.getInstance()
, specify the import to be java.util.Calendar
.While much of the code in FirstFragment.java
stays the same, you need to edit a method that creates an instance of FragmentManager
to manage the Fragment
and show the date picker.
Button
(button_first
). It should create an instance of FragmentManager
using getChildFragmentManager()
to manage the Fragment
automatically, and to show the picker. For more information about the Fragment
class, see Fragments.public void onClick(View view) {
DialogFragment newFragment = new DatePickerFragment();
newFragment.show(getChildFragmentManager(),"datePicker");
}
"datePicker"
to the string resource datepicker
.In this step you pass the date back to FirstFragment.java
, and convert the date to a string that you can show in a Toast
message.
processDatePickerResult()
method that takes the year
, month
, and day
as arguments:public void processDatePickerResult(int year, int month, int day) {
}
processDatePickerResult()
method to convert the month
, day
, and year
to separate strings, and to concatenate the three strings with slash marks for the UK date format:String month_string = Integer.toString(month+1);
String day_string = Integer.toString(day);
String year_string = Integer.toString(year);
String dateMessage = (day_string +
"/" + month_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.Toast
message:Toast.makeText(getContext, "Date: " + dateMessage,
Toast.LENGTH_SHORT).show();
"Date: "
into a string resource named date_prompt
.DatePickerFragment
, and add the following to the onDateSet()
method to invoke processDatePickerResult()
in FirstFragment
and pass it the year
, month
, and day
:@Override
public void onDateSet(DatePicker datePicker, int year, int month, int day) {
FirstFragment fragment = (FirstFragment) this.getParentFragment();
fragment.processDatePickerResult(year, month, day);
}
You use getParentFragment()
which, when used in a Fragment
, returns the parent Fragment
that this Fragment
is currently associated with. You need this because you can't call a method in FirstFragment
. The child Fragment
inherits the context, so you can use it as the context for calling the method (as in fragment.processDatePickerResult
).Toast
message.Activity
with the Basic Activity template to automatically set up the app bar, the options menu, and a floating action button.CoordinatorLayout
layout with an embedded AppBarLayout
layout. 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.AndroidManifest.xml
file so that the .MainActivity
Activity is set to use the NoActionBar
theme. This theme is defined in the themes.xml
file.MainActivity
to extend AppCompatActivity
and starts with the onCreate()
method, which sets the content view and Toolbar. It then calls setSupportActionBar()
and passes toolbar to it, setting the toolbar as the app bar for the Activity
.menu_main.xml
file. 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.onOptionsItemSelected()
method to determine which menu item was tapped.app:showAsAction
attribute in menu_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.AlertDialog
subclass of the Dialog
class to show a standard dialog for an alert.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.DialogFragment
, a subclass of Fragment
, to build a picker such as the date picker or time picker.DialogFragment
, and implement DatePickerDialog.OnDateSetListener
to create a standard date picker with a listener. Include onDateSet()
in this Fragment
.DialogFragment
subclass and add onCreateDialog()
that returns Dialog
. Initialize the date for the date picker from Calendar
, and return the dialog and these values to the Activity.FragmentManager
using getChildFragmentManager()
to manage the Fragment
and show the date picker.The related concept documentation is in 4.3: Menus and pickers.
Android Studio documentation:
Android developer documentation:
Material Design spec:
Other: