1. 程式人生 > >Android開發之ActionBar與DrawerLayout

Android開發之ActionBar與DrawerLayout

ActionBar位於Activity的頂部,可用來顯示activity的標題、Icon、Actions和一些用於互動的View。它也可被用於應用的導航。
ActionBar 是在Android 3.0(API 11)中加入到SK中的,想在低版本中使用ActionBar給專案匯入Support Library v7包即可。

使用ActionBar

開發API11以下的程式,首先必須在AndroidManifest.xml中指定Application或Activity的theme是Theme.Holo或其子類,否則將無法使用ActionBar。
如:

<application
        android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.AppCompat.Light" android:name=".BaseApplication" >

2.1 建立Actions
Actions即ActionBar中的每個互動項,通常在XML檔案中指定(位於res/menu)。在menu資原始檔中定義Action的方法如下:

<menu xmlns:android
="http://schemas.android.com/apk/res/android" xmlns:wangxiapp="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/action_search" android:icon="@mipmap/ic_action_search" //搜尋圖示的圖片 android:title
="research" android:orderInCategory="100" //此itemActionBar的位置。當有多個item時越大越在後面 wangxiapp:showAsAction="ifRoom" />
</menu>

showAsAction屬性用來定義每個Action是如何顯示的,always表示永遠顯示在ActionBar中,如果螢幕空間不夠則無法顯示,ifRoom表示螢幕空間夠的情況下顯示在ActionBar中.
在Activity中建立ctionBar的Action程式碼位於onCreateOptionsMenu()中,下面一段程式碼展示了建立過程:

    @Override  
      public boolean onCreateOptionsMenu(Menu menu) {  
        MenuInflater inflater = getMenuInflater();  
        inflater.inflate(R.menu.mainmenu, menu);   //第一個引數設定ActionBar最左邊的圖片
        return true;  
      }   

有的時候由於一些特殊原因,最左邊的圖片,即應用的圖示不顯示,此時需要一些設定。在MainActivity中新增如下程式碼:

           actionBar = getSupportActionBar();
        actionBar.setLogo(R.mipmap.ic_launcher);
        actionBar.setDisplayUseLogoEnabled(true);
        actionBar.setDisplayShowHomeEnabled(true);

執行效果如圖:

這裡寫圖片描述

現在我們看到了設定的圖片,但沒有看的我們在item中設定的title。原因是:
如果你的menu既提供了title又提供了icon屬性,那麼預設顯示icon,如果你想要顯示文字title,就新增”withText”屬性,如下:

1 <item yourapp:showAsAction="ifRoom|withText" ... />

備註:“withText”屬性是給action bar的一個暗示,告訴它應該顯示文字title,如果可以的話,就顯示,但是當icon是可用的並且action bar的空間受到限制的時候,就不一定會顯示了。

你應該為每一個item宣告title屬性,即使你不宣告title要顯示,因為:

1)如果沒有足夠的空間顯示所有的action item,那顯示在overflow中的Item就只會顯示title,此時圖片會變成豎著的三個點,點選時就會顯示title;

2)視覺受損者會讀取title;

3)如果action item只顯示icon,那麼當用戶長按item的時候,會顯示一個小的提示視窗顯示action的title;

icon是可選的,但是推薦使用。

開發者可以使用”always”宣告一個Item永遠作為action button顯示,但是開發者不應該用它迫使item用這種方式顯示,在空間狹小的裝置上,這會引起佈局問題。最好的是使用”ifRoom”。這使得系統可以根據空間做出調整。只有當Item非常重要,關係到關鍵特徵的時候,才可以使用”always”。

當點選右邊搜尋圖片時設定監聽:程式碼如下:

//佈局做如下修改
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:wangxiapp="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
     tools:context=".MainActivity">
    <item android:id="@+id/action_search"
        android:icon="@mipmap/ic_action_search"
        android:title="@string/action_settings"
        android:orderInCategory="100"
        wangxiapp:showAsAction="ifRoom"
        wangxiapp:actionViewClass="android.support.v7.widget.SearchView"
        />
</menu>
//Activty如下操作
 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        //獲取SearchView
        SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
        //設定搜尋的監聽
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
          //當搜尋提交的時候
            @Override
            public boolean onQueryTextSubmit(String query) {
                ToastUtil.showToast(UiUtil.getContext(), query);
                return true;
            }
         //當搜尋文字改變的時候
            @Override
            public boolean onQueryTextChange(String newText) {
                ToastUtil.showToast(UiUtil.getContext(), newText);
                return true;
            }
        });
        return true;
    }

如果一個Action被單擊,對於activity中的onOptionsItemSelected()將被呼叫。該函式的傳入引數是一個MenuItem。通過判斷該MenuItem的Id,即可確認是哪個Action被單擊。現在我們通過這個事件來處理通過點選ActionBar的箭頭來返回上一個Activity
這裡寫圖片描述

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        android.support.v7.app.ActionBar actionBar =  getSupportActionBar();
        actionBar.setLogo(R.mipmap.ic_launcher);
        //顯示返回主介面的箭頭
        actionBar.setDisplayUseLogoEnabled(true);
        actionBar.setDisplayShowHomeEnabled(true);
        actionBar.setDisplayHomeAsUpEnabled(true);
    }
  //ActionBar的點選監聽
   @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    //ActionBar的唯一id android.R.id.home
        if (item.getItemId()==android.R.id.home){
            finish();
        }
        return true;
    }

這樣就可以在其他Activity中通過點選ActionBar來完成返回上個Activity。其實onOptionsItemSelected()這個可以在其他Activity中省略的。在清單檔案中為該Activity設定(即可以完成點選Activty返回上個介面):

 <activity android:name=".DetailActivity"
            android:parentActivityName=".MainActivity"
            >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".MainActivity"
                />
        </activity>

3 .實現ActionBar Tab標籤
1 在Drawable 目錄下 寫了一個標籤的狀態選擇器

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- STATES WHEN BUTTON IS NOT PRESSED -->

    <!-- Non focused states -->
    <item android:state_focused="false" android:state_selected="false"
        android:state_pressed="false"
        android:drawable="@mipmap/tab_unselected" />
    <item android:state_focused="false" android:state_selected="true"
        android:state_pressed="false"
        android:drawable="@mipmap/tab_selected" />

    <!-- Focused states (such as when focused with a d-pad or mouse hover) -->
    <item android:state_focused="true" android:state_selected="false"
        android:state_pressed="false"
        android:drawable="@mipmap/tab_unselected_focused" />
    <item android:state_focused="true" android:state_selected="true"
        android:state_pressed="false"
        android:drawable="@mipmap/tab_selected_focused" />

    <!-- STATES WHEN BUTTON IS PRESSED -->

    <!-- Non focused states -->
    <item android:state_focused="false" android:state_selected="false"
        android:state_pressed="true"
        android:drawable="@mipmap/tab_unselected_pressed" />
    <item android:state_focused="false" android:state_selected="true"
        android:state_pressed="true"
        android:drawable="@mipmap/tab_selected_pressed" />

    <!-- Focused states (such as when focused with a d-pad or mouse hover) -->
    <item android:state_focused="true" android:state_selected="false"
        android:state_pressed="true"
        android:drawable="@mipmap/tab_unselected_pressed" />
    <item android:state_focused="true" android:state_selected="true"
        android:state_pressed="true"
        android:drawable="@mipmap/tab_selected_pressed" />
</selector>

2 實現自定義主題 (在values下建立resources)

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
         <!-- the theme applied to the application or activity -->
        <style name="CustomActionBarTheme"
               parent="@style/Theme.AppCompat.Light">
        <item name="android:actionBarTabStyle">@style/MyActionBarTabs</item> 

            <!-- Support library compatibility -->
            <item name="actionBarTabStyle">@style/MyActionBarTabs</item>
        </style>

        <!-- ActionBar tabs styles -->
        <style name="MyActionBarTabs"
               parent="@style/Widget.AppCompat.ActionBar.TabView">
            <!-- tab indicator -->
            <item name="android:background">@drawable/actionbar_tab_indicator</item>

            <!-- Support library compatibility -->
            <item name="background">@drawable/actionbar_tab_indicator</item>
        </style>
    </resources>

3.在Activity中設定:

      ActionBar actionBar = getSupportActionBar();
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
     ActionBar.Tab tab1 = actionBar.newTab().setText("標籤一").setTabListener(new MyTabListener());
     actionBar.addTab(tab1);
     ActionBar.Tab tab2 = actionBar.newTab().setText("標籤二").setTabListener(new MyTabListener());
     actionBar.addTab(tab2);
     ActionBar.Tab tab3 = actionBar.newTab().setText("標籤三").setTabListener(new MyTabListener());
     actionBar.addTab(tab3);
     ActionBar.Tab tab4 = actionBar.newTab().setText("標籤四").setTabListener(new MyTabListener());
     actionBar.addTab(tab4);

這裡寫圖片描述

DrawerLayout (抽屜效果):

    <android.support.v4.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" 
        android:id="@+id/dl">

        <LinearLayout
        //這裡的LinearLayout是一開始是看見的主佈局
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
           />

        <FrameLayout
               //這個佈局就是抽屜,即通過測拉才可以顯示的佈局
                android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/bg_tab"
            //抽屜在左邊
            android:layout_gravity="left">

        </FrameLayout>
    </android.support.v4.widget.DrawerLayout>

給抽屜設定監聽:
這裡寫圖片描述

ActionBarDrawerToggle :
控制抽屜的開關, 顯示在actionBar 上面 (即通過點選就可以開啟和關閉抽屜):

 ActionBar actionBar = getSupportActionBar();
 //設定顯示ActionBar的點選圖示沒,如下圖的最左邊的圖示
actionBar.setDisplayHomeAsUpEnabled(true);
     actionBar.setHomeButtonEnabled(true);
 DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
     actionBarDrawerToggle = new ActionBarDrawerToggle(MainActivity.this, drawerLayout, R.string.app_name, R.string.app_name){
          // 建立時就可以設定抽屜的監聽。關閉監聽
         @Override
         public void onDrawerClosed(View drawerView) {
             super.onDrawerClosed(drawerView);
             ToastUtil.showToast(MainActivity.this,"close");
         }
           //開啟監聽
         @Override
         public void onDrawerOpened(View drawerView) {
             super.onDrawerOpened(drawerView);
             ToastUtil.showToast(MainActivity.this, "open");
         }
     };
     //  讓開關和Actionbar建立關係 
     actionBarDrawerToggle.syncState();
        //設定監聽
     drawerLayout.setDrawerListener(actionBarDrawerToggle);

        /** 處理actionBar選單條目的點選事件 */
        public boolean onOptionsItemSelected(MenuItem item) {
            if (item.getItemId() == R.id.action_search) {
                Toast.makeText(getApplicationContext(), "搜尋", 0).show();
            }
    //返回值很重要
            return drawerToggle.onOptionsItemSelected(item)|super.onOptionsItemSelected(item);
        }

這裡寫圖片描述