Android中的常量 DEFAULT_KEYS_SHORTCUT

來源:互聯網
上載者:User

1.  關於 DEFAULT_KEYS_SHORTCUT  的 API文檔介紹
Use with setDefaultKeyMode(int) to execute a menu shortcut in default key handling.

That is, the user does not need to hold down the menu key to execute menu shortcuts.

 

從字面上看,其含義是指,將預設的按鍵輸入作為菜單快速鍵進行處理。

也就是說,使用者不需要按下menu按鍵,就可以處理菜單快速鍵,聽起來非常神奇,究竟是不是這樣呢?

 

 


--------------------------------------------------------------------------------

2.編寫樣本程式
我們編寫一個程式驗證一下其功能,首先建立一個工程,並設定預設按鍵模式為 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); 
         
        setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT); 
    } 

 

 

 

為預設的main.xml中的TextView增加一個id屬性,之後我們會用菜單選項控制這行字的顏色

 

[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" 
    /> 
 

 

 

 

使用findViewById擷取上一步中定義了id的文字物件,將其引用儲存在成員變數b中。

重寫onPrepareOptionsMenu方法,增加我們自己的功能表項目,並註冊快速鍵,同時增加菜單點擊的響應事件。

 

[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); 
         
        setDefaultKeyMode(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; 
    } 

 

 

 

注意我們一共註冊了兩個功能表項目,

一個叫“One”,點擊時將文字物件 b 的背景顏色改為紅色,同時定義其快速鍵為0

一個叫“Two”,點擊時將文字物件 b 的背景顏色改為綠色,同時定義其快速鍵為1

 

至此樣本程式完成。

 


--------------------------------------------------------------------------------

3.驗證使用樣本程式
啟動AVD,運行上述程式,程式啟動後,我們應當看到是黑底灰字,點擊menu按鈕,可以看到One和Two兩個菜單選項。

如所示:

 

 

 

目前Menu是開啟狀態,

點擊One ,將把“helloworld...”字樣的背景色變為紅色,

點擊Two ,將把“helloworld...”字樣的背景色變為紅綠色。

或者我們點設定好的快速鍵 0 和 1,發現可以直接調用菜單選項控制顏色變化。

 

到目前為止一切都很正常,不過,神奇的現在來了!

 

我們首先關閉菜單,

然後直接點鍵盤鍵"0“,看看會發生什麼。再直接點鍵盤鍵"1" ,看看會發生什麼。

哈哈,在沒有啟用菜單的情況下,功能表項目快速鍵被直接調用了!根本不需要開啟菜單,就可以用啟用菜單快速鍵!

 

什嗎?有位同學說快速鍵就應該是這樣子把,那好,請你把 onCreate 裡面的

setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT); 改為 setDefaultKeyMode(DEFAULT_KEYS_DISABLE);

然後再運行試試,在不開啟菜單的情況下,你就是把 0 和 1 按壞,系統也不會理你的呵呵

 


--------------------------------------------------------------------------------

4.淺析實現原理
那麼這神奇的功能是如何?的呢?我們試著通過分析android源碼找到答案。

 

首先順藤摸瓜,我們找一找系統是如何處理 DEFAULT_KEYS_SHORTCUT 關鍵字的,

在Activity.java中可以找到如下程式碼片段:

 

 

[java] 
if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) { 
    return false; 
} else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) { 
    if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,  
            keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE)) { 
        return true; 
    } 
    return false; 

 

 

由此可知,當系統檢測到 DEFAULT_KEYS_SHORTCUT 關鍵字時,實際調用了

getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,

keyCode, event,Menu.FLAG_ALWAYS_PERFORM_CLOSE)

 

我們繼續追尋,但是這裡會遇到一個困難,就是查閱API文檔你會發現,performPanelShortcut函數是個純虛函數!

接下來該怎麼辦呢?既然功能順利執行了,那麼這個純虛函數一定會有一個實現的。這個實作類別必然是window類的子類。

所以我們在OnCreate裡面加上一行代碼 Window w =  this.getWindow();

然後通過Eclipse的調試器,利用RTTI查看其實作類別,結果如:

可以看的很清楚,實作類別是 PhoneWindow ,

這樣我們就可以到 PhoneWindow 的源碼中去尋找performPanelShortcut的實現了。

 

在PhoneWindow.java中我們可以看到如下程式碼片段:

 

[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 on it 
    handled = st.menu.performShortcut(keyCode, event, flags); 

 

 

終於看到menu字樣了,這裡我們可以看到 if 裡面描述的調用條件,

首先當前panel必須已經準備好了(你可以用 onPreparePanel 截獲到準備請求),

其次,當前panel必須是有Menu的!(st.menu != null),

從這裡我們可以明白DEFAULT_KEYS_SHORTCUT對於沒有menu的應用是沒有任何效果的。

而且在另一處代碼我們會看到還要進行 isShortCut 的判斷,所以對於沒有快速鍵的菜單也是沒有任何效果的。

 

那麼我們再看看 preparePanel 裡面是如何?的,在其實現中可以找到如下程式碼片段:

 

[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; 

 

 

至此,就完全明白了!代碼在這裡回調了 onPreparePanel ,而 onPreparePanel  中會回調  onPrepareOptionsMenu ,

而onPrepareOptionsMenu ,就是我們自己寫實現自訂菜單的地方了。

 

為了驗證上述推導,我們在onPrepareOptionsMenu 中放入斷點,然後在菜單關閉的情況下,輸入快速鍵,

運行到斷點後查看呼叫堆疊,入所示:



 

 

堆棧調用順序可以很清楚的看出我們的推導過程是正確的。至此 DEFAULT_KEYS_SHORTCUT 的實現分析完畢。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.