Android開發筆記(一百一十九)工具列ToolBar

來源:互聯網
上載者:User

標籤:

Toolbar在前面的博文《Android開發筆記(二十)頂部導覽列》中,我們學習了ActionBar的用法,可是ActionBar著實是不怎麼好用,比如文字風格不能定製、表徵圖不能定製,而且還存在低版本的相容性問題,所以實際開發中大家還是不傾向使用ActionBar。為此,Android提供了加強版的工具列控制項即Toolbar,因為Toolbar繼承自ViewGroup,而且可在布局檔案中像其它布局視圖一樣使用,所以靈活性大大的提高了。既然Android都與時俱進了,那我們也不能落後,現在就來好好學學Toolbar的用法。


匯入android-support-v7-appcompatToolbar包含在android-support-v7-appcompat.jar包中,但app工程還不能直接使用這個jar包,因為v7-appcompat是一個完整的工程,jar包裡面大量引用了工程中的圖片資源,所以我們要先把v7-appcompat匯入為一個庫工程,然後app工程再引用這個庫工程。具體步驟如下所示:
1、SDK的Extra組件中的“Android Support Library”要更新到最新版本。
2、把v7-appcompat匯入為一個庫工程,v7-appcompat的源路徑是sdk\extras\android\support\v7\appcompat。
3、把project.properties中的target改為23(注意庫工程和app工程都要改),不然會出現如下錯誤:
Error:Error retrieving parent for item: No resource found that matches the given name ‘android:TextAppearance.Material.Widget.Button.Inverse‘.  
Error:Error retrieving parent for item: No resource found that matches the given name ‘android:Widget.Material.Button.Colored‘.  
4、刪除values-v11與values-v14下面的styles.xml(注意庫工程和app工程都要刪),不然編譯報錯:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.exmtoolbar/com.example.exmtoolbar.MainActivity}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.


在項目中引入Toolbar因為Toolbar與ActionBar都佔著頂部導覽列的位置,所以要想引入Toolbar就得先關閉ActionBar啦,具體步驟如下所示:
1、在styles.xml中定義一個不包含ActionBar的風格樣式
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">        <item name="colorPrimary">@color/blue_light</item>        <item name="colorPrimaryDark">@color/blue_light</item>        <item name="colorAccent">@color/blue_light</item>    </style>
2、修改AndroidManifest.xml,把application節點的android:theme屬性值改為第一步定義的風格,如android:theme="@style/AppBaseTheme"
3、頁面配置檔案的根節點改為LinearLayout,且為vertical垂直方向;然後增加一個Toolbar元素,因為Toolbar本質是個ViewGroup,所以也可在它下面添加別的控制項。下面是個布局例子片段:
    <android.support.v7.widget.Toolbar        android:id="@+id/tl_head"        android:layout_width="match_parent"        android:layout_height="wrap_content" />
4、Activity代碼改為繼承AppCompatActivity,注意早期的v7包是沒有AppCompatActivity的,所以前面才說要先把v7封裝更新到最新版本。
5、同樣修改AndroidManifest.xml,給該activity節點補充屬性值android:theme="@style/AppBaseTheme"
6、回到Activity代碼,擷取一個Toolbar對象,並調用setSupportActionBar方法設定預設的導覽列為當前的Toolbar。


Toolbar的常用方法Toolbar比ActionBar靈活,主要便是它提供了多個方法來修改控制項風格,下面是Toolbar的常用方法:
setLogo : 設定工具列表徵圖。
setTitle : 設定標題文字。
setTitleTextAppearance : 設定標題的文字風格。
setTitleTextColor : 設定標題的文字顏色。
setSubtitle : 設定副標題文字。副標題在標題下方。
setSubtitleTextAppearance : 設定副標題的文字風格。
setSubtitleTextColor : 設定副標題的文字顏色。
setNavigationIcon : 設定互動中心圖示。互動中心圖示在工具列表徵圖左邊。
setNavigationOnClickListener : 設定互動中心圖示的點擊監聽器。
setOverflowIcon : 設定溢出菜單的按鈕表徵圖。
showOverflowMenu : 顯示溢出菜單表徵圖。
hideOverflowMenu : 隱藏溢出菜單表徵圖。
dismissPopupMenus : 關閉已彈出的菜單。


SearchViewv7包在帶來Toolbar的同時,也帶來了一個加強版的SearchView。有關原SearchView的使用說明參見《Android開發筆記(二十)頂部導覽列》,新舊兩個SearchView的用法其實大同小異,當然新版的功能會更強大些,下面是android.widget.SearchView與android.support.v7.widget.SearchView的主要區別:

二者在調用時的區別:
1、菜單布局檔案中,舊SearchView的寫法是android:actionViewClass="android.widget.SearchView",而新SearchView的寫法是app:actionViewClass="android.support.v7.widget.SearchView"
2、代碼中擷取SearchView對象,新控制項還可通過v7類MenuItemCompat的getActionView方法來擷取。
SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem);

二者在功能上的區別:
1、編輯框其實是個SearchAutoComplete控制項,該控制項在舊SearchView中是隱藏的,在新SearchView中是開放的,所以我們可隨意修改v7編輯框的顯示風格。
2、基於上一點,新控制項可取到SearchAutoComplete的對象,因此我們可給該對象註冊自動完成的字串適配器,在使用者輸入文字時,介面會自動彈出符合搜尋條件的關鍵詞列表;
3、setAppSearchData方法在舊SearchView中是隱藏的,在新SearchView中是開放的,所以舊控制項只能傳遞搜尋文本給結果頁面,而新控制項允許傳遞其他的額外資訊給搜尋結果頁面。


Toolbar運行問題處理集錦更換導覽列還是存在一些相容問題的,下面是博主發現的幾個情況及其解決辦法:

1、溢出菜單的功能表項目已經設定為android:showAsAction="ifRoom",但即使工具列上還有空間,該功能表項目也不會顯示在工具列上。解決辦法:
在菜單布局檔案的menu根節點增加屬性xmlns:app="http://schemas.android.com/apk/res-auto",然後把android:showAsAction="ifRoom"改為app:showAsAction="ifRoom"。

2、溢出菜單列表在菜單文字左側顯示表徵圖的方法,使用ActionBar時正常,使用Toolbar時反而不會顯示表徵圖了。解決辦法:
ActionBar的featureId是8,Toolbar的featureId是108,所以在表徵圖顯示方法內部,要同時判斷這兩個數值,而不能像以前那樣僅僅判斷Window.FEATURE_ACTION_BAR。修改之後的表徵圖顯示方法如下:
    //顯示OverflowMenu的Icon public static void setOverflowIconVisible(int featureId, Menu menu) {//ActionBar的featureId是8,Toolbar的featureId是108        if (featureId%100 == Window.FEATURE_ACTION_BAR && menu != null) {            if (menu.getClass().getSimpleName().equals("MenuBuilder")) {                try {                    Method m = menu.getClass().getDeclaredMethod(                            "setOptionalIconsVisible", Boolean.TYPE);                    m.setAccessible(true);                    m.invoke(menu, true);                } catch (Exception e) {                    Log.d(TAG, e.getMessage());                }            }        }    }

3、代碼中調用getActionView方法擷取SearchView對象時,發現取到的SearchView為空白。解決辦法:
把菜單布局檔案裡的android:actionViewClass="android.support.v7.widget.SearchView"改為app:actionViewClass="android.support.v7.widget.SearchView"。


下面是新版Toolbar與SearchView的使用:



下面是新版Toolbar與SearchView的使用程式碼範例:
import java.util.Date;import com.example.exmtoolbar.util.Utils;import android.support.v4.view.MenuItemCompat;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.SearchView;import android.support.v7.widget.Toolbar;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ArrayAdapter;import android.widget.TextView;import android.widget.Toast;import android.app.SearchManager;import android.app.SearchableInfo;import android.content.ComponentName;import android.content.Context;import android.graphics.Color;import android.os.Bundle;public class MainActivity extends AppCompatActivity  {private final static String TAG = "MainActivity";private TextView tv_desc;private String[] mFormatArray = {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd","yyyy年MM月dd日HH時mm分ss秒", "yyyy年MM月dd日"};private String mFormat = mFormatArray[0];private Date mNowTime = new Date();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv_desc = (TextView) findViewById(R.id.tv_desc);        Toolbar tl_head = (Toolbar) findViewById(R.id.tl_head);        tl_head.setBackgroundResource(R.color.blue_light);        tl_head.setLogo(R.drawable.ic_launcher);        tl_head.setTitle("標題");        tl_head.setSubtitle("副標題");        tl_head.setNavigationIcon(R.drawable.ic_back);        setSupportActionBar(tl_head);}private void initSearchView(Menu menu) {MenuItem menuItem = menu.findItem(R.id.menu_search);SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem);    if(searchView == null){        Log.d(TAG, "Fail to get SearchView.");    } else {    //新舊SearchView公用代碼開始    searchView.setIconifiedByDefault(true);    searchView.setSubmitButtonEnabled(true);        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);        ComponentName cn = new ComponentName(this, SearchResultActvity.class);        SearchableInfo info = searchManager.getSearchableInfo(cn);         if(info == null){             Log.d(TAG, "Fail to get SearchResultActvity.");         }              searchView.setSearchableInfo(info);    //新舊SearchView公用代碼結束                sac_text = (SearchView.SearchAutoComplete) searchView.findViewById(R.id.search_src_text);        sac_text.setTextColor(Color.WHITE);        sac_text.setHintTextColor(Color.WHITE);searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {@Overridepublic boolean onQueryTextSubmit(String query) {return false;}@Overridepublic boolean onQueryTextChange(String newText) {doSearch(newText);return true;}});                Bundle bundle = new Bundle();        bundle.putString("hi", "hello");        searchView.setAppSearchData(bundle);    }}private SearchView.SearchAutoComplete sac_text;private String[] hintArray = {"ab", "abc", "abcde", "abHtp", "aaeet", "aab"};private void doSearch(String text) {if (text.indexOf("a") == 0) {ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_auto, hintArray);sac_text.setAdapter(adapter);        sac_text.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {TextView tv_item = (TextView) view;sac_text.setText(tv_item.getText());}        });}}    @Override      public boolean onMenuOpened(int featureId, Menu menu) {    //顯示功能表項目左側的表徵圖        Utils.setOverflowIconVisible(featureId, menu);          return super.onMenuOpened(featureId, menu);      }    @Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);//對搜尋方塊做初始化initSearchView(menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {int id = item.getItemId();if (id == android.R.id.home) {finish();} else if (id == R.id.menu_refresh) {mNowTime = new Date();tv_desc.setText("當前重新整理時間: "+Utils.getFormatDateTime(mNowTime, mFormat));return true;} else if (id == R.id.menu_about) {Toast.makeText(this, "這個是工具列的示範demo", Toast.LENGTH_LONG).show();return true;} else if (id == R.id.menu_quit) {finish();}return super.onOptionsItemSelected(item);}}






點此查看Android開發筆記的完整目錄

Android開發筆記(一百一十九)工具列ToolBar

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.