Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發筆記(一百一十九)工具欄ToolBar

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

編輯:關於Android編程

Toolbar

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

導入android-support-v7-appcompat

Toolbar包含在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的風格樣式
2、修改AndroidManifest.xml,把application節點的android:theme屬性值改為第一步定義的風格,如android:theme="@style/AppBaseTheme"
3、頁面布局文件的根節點改為LinearLayout,且為vertical垂直方向;然後增加一個Toolbar元素,因為Toolbar本質是個ViewGroup,所以也可在它下面添加別的控件。下面是個布局例子片段:
    
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 : 關閉已彈出的菜單。

SearchView

v7包在帶來Toolbar的同時,也帶來了一個加強版的SearchView。新舊兩個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();

	@Override
	protected 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() {
				@Override
				public boolean onQueryTextSubmit(String query) {
					return false;
				}

				@Override
				public 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 adapter = new ArrayAdapter(
					this, R.layout.list_auto, hintArray);
			sac_text.setAdapter(adapter);
	        sac_text.setOnItemClickListener(new OnItemClickListener() {
				@Override
				public 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);  
    }  
  
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		//對搜索框做初始化
		initSearchView(menu);
		return true;
	}

	@Override
	public 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);
	}

}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved