1. Introduction to the DEFAULT_KEYS_SHORTCUT API documentation
Use with setdefakeykeymode (int) to execute a menu shortcut cut in default key handling.
That is, the user does not need to hold down the menu key to execute menu shortcuts.
Literally, it means to process the default key input as a menu shortcut.
That is to say, the user can process the menu shortcut without pressing the menu button. It sounds amazing, isn't it?
--------------------------------------------------------------------------------
2. Compile the sample program
Let's write a program to verify its function. First, create a project and set the default key mode to DEFAULT_KEYS_SHORTCUT.
[Java]
Package com. silenceburn;
Import android. app. Activity;
Import android. OS. Bundle;
Public class MenuShortCutTester extends Activity {
/** Called when the activity is first created .*/
@ Override
Public void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. main );
Setdefakeykeymode (DEFAULT_KEYS_SHORTCUT );
}
}
Add an id attribute for TextView in the default main. xml file. Then, we use the menu option to control the color of this line.
[Xhtml]
Http://schemas.android.com/apk/res/android"
Android: orientation = "vertical"
Android: layout_width = "fill_parent"
Android: layout_height = "fill_parent"
>
Android: id = "@ + id/myText"
Android: layout_width = "fill_parent"
Android: layout_height = "wrap_content"
Android: text = "@ string/hello"
/>
Use findViewById to obtain the Text object of the id defined in the previous step and save its reference to member variable B.
Override the onPrepareOptionsMenu method, add our own menu items, register the shortcut keys, and add the RESPONSE event for menu clicking.
[Java]
Package com. silenceburn;
Import android. app. Activity;
Import android. OS. Bundle;
Import android. view. Menu;
Import android. view. MenuItem;
Import android. view. MenuItem. OnMenuItemClickListener;
Import android. widget. TextView;
Public class MenuShortCutTester extends Activity {
/** Called when the activity is first created .*/
TextView B;
@ Override
Public void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. main );
B = (TextView) this. findViewById (R. id. myText );
Setdefakeykeymode (DEFAULT_KEYS_SHORTCUT );
}
@ Override
Public boolean onPrepareOptionsMenu (Menu menu ){
// TODO Auto-generated method stub
Super. onPrepareOptionsMenu (menu );
Menu. removeItem (0 );
Menu. removeItem (1 );
Menu. add (0, 0, 0, "One"). setShortcut ('0', '0'). setOnMenuItemClickListener (new OnMenuItemClickListener (){
@ Override
Public boolean onMenuItemClick (MenuItem item ){
// TODO Auto-generated method stub
B. setBackgroundColor (android. graphics. Color. RED );
Return true;
}});
Menu. add (0, 1, 0, "Two"). setShortcut ('1', '1'). setOnMenuItemClickListener (new OnMenuItemClickListener (){
@ Override
Public boolean onMenuItemClick (MenuItem item ){
// TODO Auto-generated method stub
B. setBackgroundColor (android. graphics. Color. GREEN );
Return true;
}});
Return true;
}
}
Note that we have registered two menu items,
One is called "One". When you click it, the background color of Text object B is changed to red, and its shortcut key is set to 0.
One is "Two". When you click it, change the background color of Text object B to green, and set its shortcut key to 1.
So far, the sample program has been completed.
--------------------------------------------------------------------------------
3. Verify the sample program
Start AVD and run the above program. After the program is started, we should see the black background. Click the menu button to see the One and Two menu options.
As shown in:
Currently, the Menu is open,
Click One to change the background color of "helloworld..." to red,
Click Two to change the background color of "helloworld..." to red and green.
Or click the shortcut keys 0 and 1. You can directly call the menu options to control the color change.
Everything has been normal so far, but it's amazing now!
First, close the menu,
Click the keyboard key "0" to see what will happen. Click the keyboard key "1" to see what will happen.
Haha, the shortcut key of the menu item is directly called when the menu item is not activated! You can activate the menu shortcut without opening the menu!
What? Some people said that the shortcut key should be like this. Well, please put
Setdefakeykeymode (DEFAULT_KEYS_SHORTCUT); change to setdefakeykeymode (DEFAULT_KEYS_DISABLE );
Run it again. If you do not open the menu, press 0 and 1, and the system will not handle you.
--------------------------------------------------------------------------------
4. Analysis of Implementation Principles
How can this magical function be implemented? We try to find the answer by analyzing the android source code.
First, let's find out how the system processes the DEFAULT_KEYS_SHORTCUT keyword,
The following code snippet can be found in Activity. java:
[Java]
If (mdefakeykeymode = DEFAULT_KEYS_DISABLE ){
Return false;
} Else if (mdefakeykeymode = DEFAULT_KEYS_SHORTCUT ){
If (getWindow (). Fig cut (Window. FEATURE_OPTIONS_PANEL,
KeyCode, event, Menu. flag_always_{m_close )){
Return true;
}
Return false;
}
It can be seen that when the system detects the DEFAULT_KEYS_SHORTCUT keyword, the system actually calls
GetWindow (). extends mpanelshortcut (Window. FEATURE_OPTIONS_PANEL,
KeyCode, event, Menu. flag_always_{m_close)
We will continue to pursue it, but here we will encounter a difficulty, that is, reading the API documentation you will find that the performPanelShortcut function is a pure virtual function!
What should we do next? Since the function is successfully executed, this pure virtual function must be implemented. This implementation class must be a subclass of the window class.
So we add a line of code in OnCreate Window w = this. getWindow ();
Use the Eclipse debugger and RTTI to view its implementation class. The result is as follows:
You can see clearly that the implementation class is PhoneWindow,
In this way, we can go to the source code of PhoneWindow to find the performPanelShortcut implementation.
In PhoneWindow. java, we can see the following code snippet:
[Java]
// Only try to perform menu shortcuts if preparePanel returned true (possible false
// Return value from application not wanting to show the menu ).
If (st. isPrepared | preparePanel (st, event) & st. menu! = Null ){
// The menu is prepared now, perform the shortcut cut on it
Handled = st. menu. javasmshortcut (keyCode, event, flags );
}
Finally, we can see the call conditions described in if,
First, the current panel must be ready (you can use onPreparePanel to intercept the preparation request ),
Second, the current panel must have a Menu! (St. menu! = Null ),
Here we can understand that DEFAULT_KEYS_SHORTCUT cut has no effect on applications without menus.
In addition, we can see the isShortCut judgment in another code, so there is no effect on menus without shortcuts.
Then let's take a look at how the preparePanel is implemented. In its implementation, we can find the following code snippet:
[Java]
// Callback and return if the callback does not want to show the menu
If (! Cb. onPreparePanel (st. featureId, st. createdPanelView, st. menu )){
Return false;
}
So far, we fully understand! The Code calls back onPreparePanel, while onPreparePanel calls back onPrepareOptionsMenu,
OnPrepareOptionsMenu is the place where we write and implement custom menus.
To verify the above derivation, we place a breakpoint in onPrepareOptionsMenu and enter the shortcut key when the menu is disabled,
View the call stack after running to the breakpoint, as shown in:
The stack call sequence clearly shows that our derivation process is correct. So far, the implementation of DEFAULT_KEYS_SHORTCUT has been analyzed.