Please refer to the textbook to fully understand and complete the section of this chapter ...
Copy the engineering Ch12 and rename the project catalog to CH16.
In the honeycomb version of the system, Android introduced a new action bar. The action bar not only replaces the traditional title bar (title bar) used to display the title and app icon, but also provides additional features such as placing menu options, configuring app icons as navigation buttons, and more.
In this chapter, we will create a menu for the Criminalintent app that provides a menu item for the user to add a crime record to, and then let the app's icon support the up-navigation operation, as shown in 16-1.
Figure 16-1 Creating the Options Menu file 16.1 Options Menu
The menu that can be displayed on the action bar is called the Options menu . The Options menu provides options for the user to pop up a full-screen activity interface or to exit the current app. A new crime record is a good example. Instead of deleting the crime record from the list, it is more appropriate to use the context menu to handle the action. Because deleting a record requires knowing the context information, which crime record should be deleted. In the 18th chapter, we will learn how to use context menus.
Some string resources are required for the Options menu in this chapter and for the context menu in chapter 18th. Refer to Code listing 16-1 to add the string resources required for these two chapters to the String.xml file. Although these new string resources may not be understood now, it is necessary to complete the additions now. This way, when they are needed, they can be used directly without having to stop the work at hand.
Code Listing 16-1 Adding a string resource to a menu (Res/values/strings.xml)
Placing the Options menu on the action Bar is new, but the options menu itself already existed at the time Android came out, as shown in 16-2.
Figure 16-2 Honeycomb Previous Options Menu
Not bad, the options menu basically has no compatibility issues. However, although the code is the same, depending on the API level, each device renders the options menu in a slightly different way. Later in this chapter, we'll take a look at the compatibility, Options menu, and action bar issues that might be involved. 16.1.1 in the XML the Options menu is defined in the file
A menu is a resource that is similar to a layout. Create an XML file that defines the menu, and then place it in the project's Res/menu directory. Android automatically generates the corresponding resource ID for the XML file, which is used to generate the menu in the code.
In the project, first find the Res directory under the menu subdirectory. Then right-click the menu subdirectory and select the New→menu Resource File menu item. In the popup window interface, make sure the menu file resource type is selected and name the new file as shown in Fragment_crime_list.xml,16-3.
Figure 16-3 Creating the Options menu file
Open the newly created fragment_crime_list.xml, and add a new item element, referring to code listing 16-2.
Code Listing 16-2 Creating a menu resource (fragment_crime_list.xml)
showAsAction
The overflow property is used to specify whether the menu options are displayed on the action bar or hidden in the overflow menu . The property is currently set ifRoom
to withText
a combined value of and. Therefore, as long as there is enough space, the menu item icon and its text description will appear on the action bar. If the space is only sufficient to display the menu item icon, no text description is displayed. If the space size is not sufficient for any one item to display, then the menu item is shifted and hidden to the overflow menu. (After copying the icon file ic_menu_add.png, paste it into the drawable directory in the project)
How to access the overflow menu depends on the specific device. If the device has a physical menu key, you must click the key to view the overflow menu. Currently, most newer devices have canceled the physical menu key, so the overflow menu can be accessed via an icon with three dots at the far right of the action Bar, as shown in 16-4.
Figure 16-4 overflow menu in the action Bar
Property showAsAction
has two additional optional values: always
and never
. Deprecated always
, you should try to use a more convenient ifRoom
property value so that the operating system decides how to display the menu item. For those that are rarely used, the use never
is a good choice. In general, to avoid confusing user interfaces, only the menu items that users use frequently should be placed on the action bar. 16.1.2 Creating the Options menu
In code, the Activity
class provides a callback function that manages the options menu. The method that Android calls when the Options menu is required Activity
onCreateOptionsMenu(Menu)
.
However, depending on the design of the Criminalintent application, the callback function associated with the Options menu needs to be implemented in fragment rather than in the activity. Don't worry, Fragment
there's your own set of Options menu callback functions. Later, we will CrimeListFragment
implement these methods in. The following are two callback methods for selecting events for the Create Options menu and Response menu items:
public void Oncreateoptionsmenu (Menu menu, Menuinflater inflater)
public boolean onoptionsitemselected (MenuItem Item)
In Crimelistfragment.java, the override onCreateOptionsMenu(Menu, MenuInflater)
method,inflate the menu defined in Fragment_crime_list.xml, as shown in Listing 16-3.
Code Listing 16-3 inflating Options menu (Crimelistfragment.java)
In the above method, the MenuInflater.inflate(int, Menu)
method is called and the resource ID of the menu file is passed in, and the menu item defined in the file is populated into the Menu
instance.
Notice that we called the superclass onCreateOptionsMenu( )
method. Although not required, we recommend this as an agreed development specification. With the call of this superclass method, any superclass-Defined option Menu function can also be applied in the subclass method. However, the superclass method call here only follows the Convention, because Fragment
the superclass onCreateOptionsMenu()
method does nothing.
Fragment
The onCreateOptionsMenu(Menu, MenuInflater)
method is called by the FragmentManager
responsible. Therefore, when the activity receives a method callback request from the operating system onCreateOptionsMenu()
, we must tell explicitly that FragmentManager
its managed fragment should receive onCreateOptionsMenu()
the calling instruction of the method.
To notify FragmentManager
, you call the following methods:
public void Sethasoptionsmenu (Boolean hasmenu)
In the CrimeListFragment.onCreate()
method, let FragmentManager
's know how CrimeListFragment
to receive the option menu method callback, as shown in Listing 16-4.
Code Listing 16-4 Call SethasOptionsMenu
method (Crimelistfragment.java)
Run the Criminalintent app to see the newly created Options menu, shown in 16-5.
Figure 16-5 menu item icon that appears on the action bar
How is the menu item title not displayed? Most devices have limited screen space in vertical mode, so only the menu item icon is visible on the app's action bar. Click the menu icon on the Action bar to pop up the menu title, shown in 16-6.
Figure 16-6 Long Press the icon on the action Bar to display the menu item title
In horizontal mode, there is enough space on the action Bar to display both the menu icon and the item title, as shown in 16-7.
Figure 16-7 menu icons and menu titles that appear on the action bar at the same time 16.1.3 Response menu item Selection
In response to the user clicking on the [New Notes] menu item, a new method is implemented to add a new Crime
to the crime array list. In Crimelab.java, add the following method to the Crime
array list, as shown in code listing 16-5.
Code Listing 16-5 Adding a new crime (Crimelab.java)
Since crime records can be added manually, there is no need for the program to automatically generate 100 crime records. In Crimelab.java, delete the code that generated the random crime record, as shown in Listing 16-6.
Code Listing 16-6 Goodbye, random crime record! (Crimelab.java)
When a user taps a menu item in the Options menu, fragment receives onOptionsItemSelected(MenuItem)
a callback request for the method. The incoming parameter that the method accepts is an instance that describes the user's choice MenuItem
.
Although the current Options menu contains only one menu item, the menu can usually contain multiple menu items. By checking the menu item ID, you can determine which menu item is selected, and then respond accordingly. The ID of the menu item used in the code is actually the resource ID assigned to the menu item in the XML definition file.
In Crimelistfragment.java, the implementation onOptionsItemSelected(MenuItem)
method responds to the selection event of the menu item. In this method, you create a new Crime
instance, add it to it, and CrimeLab
then launch an CrimePagerActivity
instance that allows the user to edit the newly created Crime
record, as shown in Listing 16-7.
Code Listing 16-7 Response menu item selection event (Crimelistfragment.java)
Note that the onOptionsItemSelected(MenuItem)
method returns a Boolean value. Once the menu item event processing is complete, true
a value should be returned to indicate that the completed menu item selects all Tasks to be processed. Also, case
in an expression, if the menu item ID does not exist, the default superclass version method is called.
Run the Criminalintent app, try using the Options menu, add some crime records, and edit them. 16.2 Implementing hierarchical Navigation
So far, criminalintent applications rely mainly on the back key to navigate within the app. Navigation using the back key, also known as temporary navigation , can only be returned to the previous user interface. Ancestral navigation, sometimes referred to as hierarchical navigation (hierarchical navigation), can be navigated in-app step-by-step.
Android makes it easy to use the app icon on the Action bar for hierarchical navigation. You can also use the app icon to rewind directly to the main screen, that is, step up to the initial interface of your application. In fact, the app icon on the action Bar was originally used as the home key. However, Android now only recommends the use of the app icon, which allows the parent interface to go back up one level to the current activity. As a result, the app icon actually acts as an up button.
In this section, for the CrimePagerActivity
app icon that appears on the action Bar, we encode the function to have the up button. Click the icon to roll back to the crime list interface. 16.2.1 enable navigation for app icons
Typically, once an app icon is enabled for the Up navigation button, a 16-9-pointing icon appears to the left of the app icon.
Figure 16-9 Action Bar with up navigation buttons
To enable the function of the Apply icon up navigation button and display the left icon on the fragment view, call the following method to set the properties of the fragment DisplayHomeAsUpEnabled
:
public abstract void Setdisplayhomeasupenabled (Boolean showhomeasup)
This method comes from API level 11, so the system version must be judged to ensure that the application is backwards compatible and use @targetapi (11) annotations to prevent Android lint from reporting compatibility issues.
In CrimeFragment.onCreateView(...)
, call the setDisplayHomeAsUpEnabled(true)
method, as shown in Listing 16-8.
Code Listing 16-8 Enable up navigation button (Crimefragment.java)
Notice that the calling setDisplayHomeAsUpEnabled(...)
method simply turns the app icon into a button and displays a left icon. So we have to encode the function that the click button can be rolled up. For apps that have been developed at the API 11-13 level, the app icon is enabled by default as the Up button, but you still need to call setDisplayHomeAsUpEnabled(true)
the method to show the left pointing icon to the left of the app icon.
In code listing 16-8, we have a oncreateview (...)
Method uses the @targetapi annotation. Only the invocation of the setdisplayhomeasupenabled (True)
method is actually annotated. However, Oncreateview (...)
The method will soon have some specific API-level code added, so here we choose to annotate the entire Oncreateview (...) Directly
Implementation methods.
Note: Code listing 16-8, if uses the original book code will error, because getactivity (). Getactiobar () returns null in Fragment . The online solution and code are as follows:
I think I found a solution. First of all I didn ' t even see a action bar so I do some searching and found many people saying to extend the activities With actionbaractivity instead of fragmentactivity...but actionbaractvity are deprecated now, do some more searching, fou nd people saying to use appcompatactivity. So I extended crimepageractivity and singlefragmentactivity with Appcompatactivity. Then I found people solving the nullpointerexception by using Getsupportactionbar () instead of Getactionbar (). It couldn ' t find Getsupportactionbar () though, until casting with appcompatactivity. So finally my code looks like this:
if (Build.VERSION.SDK_INT >= build.version_codes. Honeycomb) {
Getactivity (). Getactionbar (). Setdisplayhomeasupenabled (True);
}
Switch
if (Build.VERSION.SDK_INT >= build.version_codes. Honeycomb) {
((appcompatactivity) getactivity ()). Getsupportactionbar ()
. setdisplayhomeasupenabled (True);
}
16.2.2 Response up Button
As with the response Options menu item, you can onOptionsItemSelected(MenuItem)
respond to an app icon that has the UP button enabled by overriding the method. Therefore, you should first inform Fragmentmanager: The CrimeFragment
callback method associated with the option menu will be implemented on behalf of its managed activity. As with the previous pair CrimeListFragment
, the method is called in the CrimeFragment.onCreate(...)
method, setHasOptionsMenu(true)
as shown in Listing 16-9.
Code Listing 16-9 Open Options Menu processing (Crimefragment.java)
You do not need to define or generate an app icon menu item in an XML file. It already has a ready-made resource id:android.r.id.home. In Crimefragment.java, the override onOptionsItemSelected(MenuItem)
method responds to a user's Click event on the menu item, as shown in Listing 16-10.
Code Listing 16-10 Response app icon (home key) menu item (Crimefragment.java)
To enable the user to click the Up button to return to the crime list interface, we might want to create a intent and then launch the CrimePagerActivity
instance, such as the following implementation code:
Intent Intent = new Intent (getactivity (), crimelistactivity.class);
Intent.addflags (Intent.flag_activity_clear_top);
StartActivity (Intent);
Finish ();
FLAG_ACTIVITY_CLEAR_TOP
Indicates that Android looks for an existing instance of the specified activity in the fallback stack, as shown in 16-10. If present, all other activity in the stack pops up so that the activated activity appears on the top of the stack and is displayed on the screen.
Figure 16-10 in the work of FLAG_ACTIVITY_CLEAR_TOP
However, Android has a better way to achieve hierarchical navigation: Use the NavUtils
metadata in the convenience class with the manifest configuration file.
To process the metadata first. Open the Androidmanifest.xml file, CrimePagerActivity
add a new attribute to the declaration, and meta-data
specify CrimePagerActivity
the parent class as CrimeListActivity
shown in Listing 16-11.
Code Listing 16-11 Adding parent Activity Metadata Properties (Androidmanifest.xml)
Think of metadata tags as a sticky post posted on your activity. Information like this is stored in the system PackageManager
. Anyone who knows the name of a sticky sticker can get its content. You can also create your own name-value (name-value) pairs to get them when you need them. This particular name-value pair NavUtils
is defined by the class so that it can know who is the parent of the specified activity, especially useful with the following NavUtils
class methods:
public static void Navigateupfromsametask (Activity sourceactivity)
In a CrimeFragment.onOptionsItemSelected(...)
method, NavUtils.getParentActivityName(Activity)
you first check whether the parent activity is specified in the metadata by calling the method. If the parent activity is specified, the navigateUpFromSameTask(Activity)
method is called and the parent activity interface is navigated to. As shown in Listing 16-12.
Code Listing 16-12 Use NavUtils
class (Crimefragment.java)
If no parent activity is specified in the metadata, to avoid misleading the user, the left arrow icon is no longer displayed. Back in the onCreateView(...)
method, check that the setDisplayHomeAsUpEnabled(true)
parent activity exists before calling the method, as shown in Listing 16-13.
Code Listing 16-13 Controlling the display of navigation icons (Crimefragment.java)
Why is it NavUtils
better to use a class than to manually start activity? First, NavUtils
the class implementation code is both concise and elegant. Second, the use NavUtils
of classes can also be implemented in the manifest configuration file to manage the relationship between the activity. If the relationship between the activity changes, without the effort to modify the Java code, we simply modify a single line of code in the configuration file.
In addition, the use NavUtils
of classes also preserves the separation of hierarchical relational processing from fragment code. This CrimeFragment
will work correctly even if you use the same in each activity with different parent classes CrimeFragment
.
Run the Criminalintent app. Create a new crime record, and then click the Apply icon to return to the crime list interface. In fact, criminalintent application of two levels of relationships is not too easy to distinguish. However navigateUpFromSameTask(Activity)
, the method implements the function of upward navigation, which makes it easy for the user to navigate up to CrimePagerActivity
the parent-class interface. 16.3 Optional Menu Items
This section, using the previous knowledge about menus, application compatibility, and optional resources, we add a menu item implementation to show or hide CrimeListActivity
the sub-headings of the action Bar. 16.3.1 Create an optional menu XML file
For users who use the system version prior to Honeycomb, only the menu items that apply to the action bar should be invisible to them. Therefore, you should first create an optional menu resource that can be used by the system version of the API level 11. Create a menu-v11 directory under the project's res directory, and then copy the Fragment_crime_list.xml file to the directory.
Open the Res/menu-v11/fragment_crime_list.xml file, and add a new menu item that appears as show subtitle, referring to code listing 16-14. If there is enough space, it will appear on the action bar.
Code Listing 16-14 Add Show subtitle menu item (res/menu/fragment_crime_list.xml)
In the onOptionsItemSelected(...)
method, set the caption of the action Bar to respond to the Click event for the menu item, as shown in Listing 16-15.
Code Listing 16-15 Response Show subtitle menu item click event (Crimelistfragment.java)
Note that this is just a matter of using annotations in your code to @TargetApi(11)
prevent Android lint from reporting compatibility issues. The related code of the action Bar is not placed in the version condition judgment. On previous versions of the device, it will not R.id.menu_item_show_subtitle
appear, and the Action Bar related code will not be invoked, so there is no need to deal with device compatibility issues.
Run the Criminalintent app on the new device and use the new menu to display sub-headings. The app is then run on a froyo or gingerbread device (either a virtual device or a physical device). Click the menu key to confirm that show subtitle is not displayed. Finally, add a new crime record to confirm that the app is running as before. 16.3.2 Toggle menu item Title
When the caption on the action bar is displayed, the menu item title still appears as " 显示子标题
". The user experience is better if the toggle of the menu item title is linked to the display or concealment of the sub-headings.
In the onOptionsItemSelected(...)
method, after the menu item is selected, check the display status of the sub-caption and take the appropriate action, as shown in Listing 16-16.
Code Listing 16-16 Implementing the linkage display of the menu item title and sub-headings (Crimelistfragment.java)
If the caption is not displayed on the action bar, you should set the display sub-caption and toggle the menu item title so that it appears as hide Subtitle. If the subtitle is already displayed, you should set it to a null
value and switch the menu item title back to show Subtitle.
Run the Criminalintent app to confirm that the menu item title and sub-title display can be linked. 16.3.3 " There's one more question . "
This problem is the classic device rotation problem. After the subtitle is displayed, rotate the device, and the displayed subtitle disappears because the user interface is regenerated. To resolve this issue, an instance variable is required to record the display state of the sub-caption, and set the hold so CrimeListFragment
that the value of the variable remains available after the device is rotated.
In Crimelistfragment.java, add a member variable of a Boolean type, keep it in the onCreate(...)
method, CrimeListFragment
and initialize the variable, as shown in Listing 16-17.
Code Listing 16-17 preserving CrimeListFragment
and initializing variables (Crimelistfragment.java)
Then, in the onOptionsItemSelected(...)
method, set the corresponding variable value based on the selection of the menu item, as shown in Listing 16-18.
Code Listing 16-18 based on the selection settings of the menu item subtitleVisible
(Crimelistfragment.java)
Now you need to see if the sub-headings should be displayed after the device rotates. In Crimelistfragment.java, the override onCreateView(...)
method, depending on mSubtitleVisible
the value of the variable, determines whether to set the sub-caption, as shown in Listing 16-19.
Code Listing 16-19 to mSubtitleVisible
set sub-headings (Crimelistfragment.java) based on the value of a variable
You also need to see the status of the onCreateOptionsMenu(...)
sub-headings in the method to ensure that the menu item title matches the display, as shown in Listing 16-20.
Code Listing 16-20 mSubtitleVisible
the menu item title correctly (Crimelistfragment.java) based on the value of the variable
Run the Criminalintent app. Show sub-headings and rotate the device, and you can see that the sub-headings still display correctly in the recreated view.
16th Chapter Action Bar