1. 程式人生 > >Android中ActionBar中不顯示overflow(就是三個點的那個按鈕)解決辦法

Android中ActionBar中不顯示overflow(就是三個點的那個按鈕)解決辦法

最近寫安卓想實現actionbar上的一些按鈕,但是新的安卓版本似乎有問題,很難顯示出那個三個點的選單,找了很多教程,還是這個靠譜一些。


當新建android工程後,發現原來使用的ActionBar的螢幕右上角的三個點不再出現了(如圖中3),它是因為什麼原因不在出現了呢?如果不是我自己的原因,那怎麼才能搞出來。這個問題通過下面的方式已經得到了解決。 
這裡寫圖片描述

1. 為什麼這個選單鍵(三點)會不見了?

大概意思也就是說安卓也在不斷地進化中,有些東西可能被慢慢替代掉,從 Android 3.0(API 級別 11)開始,採用 Android 技術的裝置不必再提供一個專用“選單”按鈕。可以參考sHasPermanentMenuKey()方法的原始碼解釋:

Report if the device has a permanent menu key available to the user. 

As of Android 3.0, devices may not have a permanent menu key available. 
Apps should use the action bar to present menu options to users. 
However, there are some apps where the action bar is inappropriate 
or undesirable. This method may be used to detect if a menu key is present.If not, applications should provide another on-screen affordance to access functionality

2.怎麼才能搞出來選單鍵的功能呢?

關鍵點:在onCreate()方法中新增下面的方法:他的作用是通過反射的方式獲取sHasPermanentMenuKey()方法,這個方法的作用該方法可用於檢測選單鍵是否存在,並可強制讓其可見。

     try {
            ViewConfiguration config = ViewConfiguration.get(this);//得到一個已經設定好裝置的顯示密度的物件
            Field menuKeyField = ViewConfiguration.class
                    .getDeclaredField("sHasPermanentMenuKey"
);//反射獲取其中的方法sHasPermanentMenuKey(),他的作用是報告裝置的選單是否對使用者可用,如果不可用可強制視覺化。 if (menuKeyField != null) { //強制設定引數,讓其重繪三個點 menuKeyField.setAccessible(true); menuKeyField.setBoolean(config, false); } } catch (Exception e) { e.printStackTrace(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

實現步驟:

1) 在工程中的onCreate()方法中,新增如下關鍵程式碼。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getOverflowMenu();//新增方法
    }

    private void getOverflowMenu() {
        try {
            ViewConfiguration config = ViewConfiguration.get(this);//得到一個已經設定好裝置的顯示密度的物件
            Field menuKeyField = ViewConfiguration.class
                    .getDeclaredField("sHasPermanentMenuKey");//反射獲取其中的方法sHasPermanentMenuKey(),他的作用是報告裝置的選單是否對使用者可用,如果不可用可強制視覺化。
            if (menuKeyField != null) {
                //強制設定引數,讓其重繪三個點
                menuKeyField.setAccessible(true);
                menuKeyField.setBoolean(config, false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

2)重寫onCreateOptionsMenu方法,在這個方法中用getMenuInflater().inflate(R.menu.main, menu)方法填充指定的main.xml檔案,然後有兩種方法新增item,其效果不同。

A.用menu.add()方法增加內容item,這個方法就不需要在main.xml檔案中新增內容,比較方便。

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // 填充menu的main.xml檔案; 給action bar新增條目
        getMenuInflater().inflate(R.menu.main, menu);
        menu.add(0, 0, 1, "備註1");// 相當於在res/menu/main.xml檔案中,給menu增加一個新的條目item,這個條目會顯示title標籤的文字(如備註1)
        menu.add(0, 1, 2, "備註2");//第二個引數代表唯一的item ID. 
        menu.add(0, 2, 3, "備註3");
        menu.add(0, 3, 4, "備註4");
        return true;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

效果:可以正常顯示彈出的選單list。 
這裡寫圖片描述

B.在res/menu/main.xml檔案中新增item和屬性,也可以填充自定義的其他xml檔案。

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/action_settings01"
        android:icon="@drawable/ic_favorite_black_48dp"
        android:title="@string/action_settings01"
         android:showAsAction="ifRoom"/>

    <!-- 在這裡新增item-->
    <item android:id="@+id/action_settings02"
          android:title="@string/action_settings02"<!-- 只能通過屬性的方式在res/values/string.xml中新增或修改文字 -->
          android:showAsAction="ifRoom"/>
</menu>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

效果:可以顯示在ActionBar中的,但在彈出的選單List中沒有這個ID:action_settings02的item。

3.重寫onOptionsItemSelected()方法, 在點選三點後,這個方法可以根據ID指定在彈出的選單中的要顯示的item內容。其內容可以指定由menu.add()方法增加的item ID,也可以指定由xml新增的item ID(如R.id.action_settings01)。

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case 0://顯示由menu.add()方法增加內容item的ID
            Toast.makeText(getApplicationContext(), "1", 1000).show();
            return true;
        case R.id.action_settings03://顯示由xml新增的item的ID
            Toast.makeText(getApplicationContext(), "3", 1000).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

擴充套件:當三個點顯示出來後,可以在他的左側新增其他的文字或者圖示。

1.在res/menu/main.xml中新增下面的item,如果不需要讓其顯示到選單欄裡,而要它顯示在應用欄上,那麼就不能在onOptionsItemSelected()方法中使用ID定位item。 
2.showAsAction為不同關鍵屬性時,可以根據表格查詢item出現的對應狀態。當許多item使用ifRoom屬性並且空間不足時,剩餘的item不會顯示出來或者擠進三點選單中。 
這裡寫圖片描述

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
        <!-- id可以在類中使用 -->
        android:id="@+id/action_settings01"
        <!-- 如果同時出現icon圖片資源和title標題時,一般會忽略文字title內容,圖片會佔據文字的位置-->
        android:icon="@drawable/ic_favorite_black_48dp"
        <!-- 只能通過屬性的方式在res/values/string.xml中新增或修改文字 -->
        android:title="@string/action_settings01"   
        <!-- showAsAction為關鍵屬性 詳見下表 -->
         android:showAsAction="ifRoom"/>

    <item android:id="@+id/action_settings02"
          android:title="@string/action_settings02"
          android:showAsAction="ifRoom"/>

    <item android:id="@+id/action_settings03"
          android:title="@string/action_settings03"
          android:showAsAction="ifRoom"/>
</menu>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

詳細解釋:

<menu>定義 Menu,即選單項的容器。<menu> 元素必須是該檔案的根節點,並且能夠包含一個或多個 <item><group> 元素。
<item>建立 MenuItem,此元素表示選單中的一項,可能包含巢狀的 <menu> 元素,以便建立子選單。
<group>或者<item> 元素的不可見容器(可選)。它支援您對選單項進行分類,使其共享活動狀態和可見性等屬性。 
< Item >的關鍵屬性showAsAction,代表了Iitem以什麼樣的方式和什麼時機出現在APP的活動條裡(ActionBar),如下:
  • 1
  • 2
  • 3
  • 4

這裡寫圖片描述