史上最詳細的Toolbar開發(fā)講解,此篇必讀!
Toolbar的簡介
Toolbar 是 android 5.0 引入的一個新控件,Toolbar出現(xiàn)之前,我們很多時候都是使用ActionBar以及ActionActivity實現(xiàn)頂部導(dǎo)航欄的,因此Toolbar可以理解為是ActionBar的升級版。Toolbar大大擴展了ActionBar,使用更靈活,不像ActionBar那么固定,Toolbar更像是一般的View元素,可以被放置在view樹體系的任意位置,可以應(yīng)用動畫,可以跟著scrollView滾動,可以與布局中的其他view交互。
Toolbar的基本使用
1、要想使用Toolbar,首先應(yīng)該在Gradle的配置腳本里面添加V7兼容包(代碼如下,版本是楠妹妹寫本文的時候的版本),或者通過Android Studio的圖形化界面的操作方法把V7兼容包依賴進來。
- compile 'com.android.support:appcompat-v7:23.1.1'
2、在我們需要頂部導(dǎo)航欄的布局文件當(dāng)中添加Toolbar,并且配置一些常用的屬性(使用自定義屬性的時候需要注意把命名空間“app”添加到根節(jié)點)。
- xmlns:app="http://schemas.android.com/apk/res-auto"
這里只列出一些常用的屬性,比如最小高度,返回按鈕的圖標(biāo),背景等等。這里需要注意的是,屬性值中的“?”表示對Android系統(tǒng)的主題樣式進行重用。意思是如果我們改變了主題樣式中的colorPrimary屬性的話,Toolbar的背景顏色也會隨之改變,因此提醒我們?nèi)ブ黝}樣式中進行一些配置。
- <android.support.v7.widget.Toolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?attr/colorPrimary"
- android:minHeight="?actionBarSize"
- app:navigationIcon="@mipmap/arrow_left"
- app:title="標(biāo)題"/>
3、在styles.xml文件中進行一些常用的配置。由于我們使用的是
AppCompatActivity,因此必須使用AppCompat的相關(guān)主題,筆者這里使用亮色調(diào)的沒有ActionBar的主題,注意需要在清單文件當(dāng)中去使用自己定義的主題。為了完全去掉ActionBar,需要把windowActionBar、windowNoTitle以及加上android聲明的也寫上,確保把系統(tǒng)自帶的以及第三方兼容包的ActionBar都徹底去掉。
- <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
- <item name="colorPrimary">@color/red</item>
- <item name="colorPrimaryDark">@color/green</item>
- <item name="colorAccent">@color/blue</item>
- <item name="android:textColorPrimary">@color/white</item>
- <item name="android:windowActionBar">false</item>
- <item name="android:windowNoTitle">true</item>
- <item name="windowActionBar">false</item>
- <item name="windowNoTitle">true</item>
- </style>
4、下面對主題中的幾個顏色進行講解,請參考下面的圖片進行理解。
- colorPrimaryDark是我們手機最頂端的狀態(tài)欄的背景顏色(改變它需要Android5.0以及以上的手機支持才行)。
- colorPrimary是指導(dǎo)航欄的顏色。
- colorAccent是指我們常用控件比如Button等的顏色。
- textColorPrimary是指我們導(dǎo)航欄中標(biāo)題的顏色。
- windowBackground是指我們窗體的默認顏色。
- navigationBarColor是指Android手機中虛擬按鍵的背景顏色。
5、代碼中對Toolbar進行常見的操作??梢酝ㄟ^ID找到Toolbar之后,可以對導(dǎo)航圖標(biāo)進行點擊監(jiān)聽,前提必須是在布局文件或者java代碼中添加了導(dǎo)航圖標(biāo)。同理也可以使用菜單,具體看注釋,不再贅述。
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- //對Toolbar左邊的導(dǎo)航圖標(biāo)進行監(jiān)聽
- toolbar.setNavigationOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Toast.makeText(MainActivity.this, "返回", Toast.LENGTH_SHORT).show();
- }
- });
- //Toolbar中使用菜單toolbar.inflateMenu(R.menu.menu_main);
- toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_item1:
- Toast.makeText(MainActivity.this, "菜單1", Toast.LENGTH_SHORT).show();
- return true;
- case R.id.action_item2:
- Toast.makeText(MainActivity.this, "菜單2", Toast.LENGTH_SHORT).show();
- return true;
- case R.id.action_item3:
- Toast.makeText(MainActivity.this, "菜單3", Toast.LENGTH_SHORT).show();
- return true;
- } return false;
- }
- });
6、運行效果圖
Toolbar高級使用篇--自定義Toolbar
通過下面的對比可以知道,原生的Toolbar畫面太美不忍直視,一般來說要在項目當(dāng)中使用Toolbar我們都應(yīng)該去自定義Toolbar。下面開始討論如何去自定義Toolbar。
下面先讓我給出核心的要點:
- 自定義布局,添加到Toolbar當(dāng)中
- 有必要的時候自定義一些屬性
- 自定義Class繼承Toolbar,讀取自定義屬性,對Toolbar的布局顯示,內(nèi)容進行設(shè)置,***需要對外公開一些函數(shù)用于設(shè)置標(biāo)題、監(jiān)聽等。下面通過步驟來詳細說明。
1、寫一個自定義的布局,用來放入自定義Toolbar。
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- >
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp">
- <ImageView
- android:id="@+id/toolbar_leftButton"
- android:layout_width="@dimen/icon_size"
- android:layout_height="@dimen/icon_size"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:src="@mipmap/icon_background"
- android:textColor="@color/white"
- android:visibility="visible"
- />
- <ImageView
- android:id="@+id/toolbar_rightButton"
- android:layout_width="@dimen/icon_size"
- android:layout_height="@dimen/icon_size"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:src="@mipmap/icon_background"
- android:textColor="@color/white"
- android:visibility="visible"
- />
- <EditText
- android:id="@+id/toolbar_searchview"
- style="@style/search_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_gravity="center"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
- android:layout_toLeftOf="@id/toolbar_rightButton"
- android:layout_toRightOf="@id/toolbar_leftButton"
- android:drawableLeft="@mipmap/icon_search"
- android:gravity="center"
- android:hint="請輸入搜索內(nèi)容"
- android:visibility="gone"
- />
- <TextView
- android:id="@+id/toolbar_title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:layout_gravity="center"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
- android:layout_toLeftOf="@id/toolbar_rightButton"
- android:layout_toRightOf="@id/toolbar_leftButton"
- android:gravity="center"
- android:textColor="@color/white"
- android:textSize="20sp"
- android:visibility="gone"
- />
- </RelativeLayout>
- </RelativeLayout>
讓我們通過下面兩張效果圖來進行說明吧O(∩_∩)O~~。
由于一般不推薦把寬高意外的屬性寫在最外面根節(jié)點,因此我在最外面的相對布局里面又內(nèi)嵌了一個相對布局,并且設(shè)置了左右的邊距(margin)。至于如何布局要根據(jù)實際項目而定。楠妹妹這里的需求是,標(biāo)題和搜索框能夠隨時切換。因此標(biāo)題和搜索框是通過項目布局重疊在一起的,需要用到其中一個的時候就把另外一個隱藏掉。另外需要注意的地方就是,左右按鈕***也不要用Toolbar自帶的,因為可能會造成布局不對稱問題,使得標(biāo)題(搜索框)不能居中。在按鈕不使用的時候,我們并不是通過gone的方法隱藏掉的,而是通過@mipmap/icon_background空白圖片來進行占位,保持布局對稱。
2、在values文件夾新建attrs.mxl文件,用于存放自定義的一些屬性。這些屬性都可以通過字面意思讀懂,不詳細解釋了。
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <declare-styleable name="CNToolbar">
- <attr name="showSearchView" format="boolean"/>
- <attr name="leftButtonIcon" format="reference"/>
- <attr name="rightButtonIcon" format="reference"/>
- <attr name="myTitle" format="string"/>
- </declare-styleable>
- </resources>
3、自定義Class繼承Toolbar。代碼的主要工作是初始化界面還有監(jiān)聽器,對外公開操作的接口。
初始化界面的時候需要把自定義屬性的值通過TintTypedArray讀取進來,然后進行一些界面顯示方面的設(shè)置。
初始化監(jiān)聽器,需要用到接口的回調(diào)。具體步驟是公開的聲明接口,接口里面有onClick方法;聲明該接口的實現(xiàn),作為Toolbar的私有成員變量;公開setListener方法,把傳進來的Listener實現(xiàn)類賦值給這個成員變量;在必須的時候調(diào)用成員變量的onClick方法(如在左邊的按鈕的點擊事件中調(diào)用)。
公開一些函數(shù),比如設(shè)置標(biāo)題,設(shè)置是否顯示搜索框、標(biāo)題等等。
- /**
- * 自定義的導(dǎo)航欄
- */public class CNToolbar extends Toolbar {
- private TextView toolbar_title;
- private EditText toolbar_searchview;
- private ImageView toolbar_leftButton;
- private ImageView toolbar_rightButton;
- private View mChildView;
- private boolean showSearchView;
- private Drawable left_button_icon;
- private Drawable right_button_icon;
- private String title;
- public CNToolbar(Context context) {
- this(context, null, 0);
- } public CNToolbar(Context context, @Nullable AttributeSet attrs) {
- this(context, attrs, 0);
- } public CNToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr); //通過代碼得到布局文件當(dāng)中一些屬性的值
- final TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
- R.styleable.CNToolbar, defStyleAttr, 0);
- showSearchView = a.getBoolean(R.styleable.CNToolbar_showSearchView, false);
- left_button_icon = a.getDrawable(R.styleable.CNToolbar_leftButtonIcon);
- right_button_icon = a.getDrawable(R.styleable.CNToolbar_rightButtonIcon);
- title = a.getString(R.styleable.CNToolbar_myTitle);
- a.recycle(); //初始界面
- initView(); //初始監(jiān)聽器
- initListener();
- } /**
- * 初始化布局
- */
- private void initView() {
- if (mChildView == null) {
- mChildView = View.inflate(getContext(), R.layout.toolbar, null);
- toolbar_title = (TextView) mChildView.findViewById(R.id.toolbar_title);
- toolbar_searchview = (EditText) mChildView.findViewById(R.id.toolbar_searchview);
- toolbar_leftButton = (ImageView) mChildView.findViewById(R.id.toolbar_leftButton);
- toolbar_rightButton = (ImageView) mChildView.findViewById(R.id.toolbar_rightButton);
- //添加自定義的布局到Toolbar
- addView(mChildView); //設(shè)置標(biāo)題、搜索框、左右按鈕是否顯示,并且設(shè)置按鈕的圖標(biāo)
- if (showSearchView) {
- showSearchview();
- hideTitle();
- } else {
- hideSearchview();
- showTitle();
- if (title != null) {
- toolbar_title.setText(title);
- }
- } if (left_button_icon != null) {
- toolbar_leftButton.setImageDrawable(left_button_icon);
- } if (right_button_icon != null) {
- toolbar_rightButton.setImageDrawable(right_button_icon);
- }
- }
- } /**
- * 重寫設(shè)置標(biāo)題的方法
- *
- * @param title
- */
- @Override
- public void setTitle(CharSequence title) {
- toolbar_title.setText(title);
- } @Override
- public void setTitle(@StringRes int resId) {
- toolbar_title.setText(resId);
- } /**
- * 設(shè)置左右按鈕的圖標(biāo)
- *
- * @param d
- */
- public void setLeftButtonIconDrawable(Drawable d) {
- toolbar_leftButton.setImageDrawable(d);
- } public void setRightButtonIconDrawable(Drawable d) {
- toolbar_rightButton.setImageDrawable(d);
- } /**
- * 標(biāo)題與搜索框的切換
- */
- public void setShowSearchView() {
- hideTitle();
- showSearchview();
- } public void setShowTitleView(String title) {
- hideSearchview();
- showTitle();
- toolbar_title.setText(title);
- } /**
- * 左右按鈕的監(jiān)聽
- */
- private void initListener() {
- toolbar_leftButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (onLeftButtonClickListener != null) {
- onLeftButtonClickListener.onClick();
- }
- }
- });
- toolbar_rightButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (onRightButtonClickListener != null) {
- onRightButtonClickListener.onClick();
- }
- }
- });
- } public interface OnLeftButtonClickListener {
- void onClick();
- } public interface OnRightButtonClickListener {
- void onClick();
- } private OnLeftButtonClickListener onLeftButtonClickListener;
- private OnRightButtonClickListener onRightButtonClickListener;
- public void setOnLeftButtonClickListener(OnLeftButtonClickListener listener) {
- onLeftButtonClickListener = listener;
- } public void setOnRightButtonClickListener(OnRightButtonClickListener listener) {
- onRightButtonClickListener = listener;
- } /**
- * 設(shè)置標(biāo)題或者搜索框是否顯示
- */
- private void showTitle() {
- toolbar_title.setVisibility(View.VISIBLE);
- } private void hideTitle() {
- toolbar_title.setVisibility(View.GONE);
- } private void showSearchview() {
- toolbar_searchview.setVisibility(View.VISIBLE);
- } private void hideSearchview() {
- toolbar_searchview.setVisibility(View.GONE);
- }
- }
- 4、使用,在必須的地方如同一般的控件去使用就可以了,注意加上自定義屬性的命名空間,一般為auto就可以了。
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <com.nan.cnshop.widget.CNToolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?attr/colorPrimary"
- android:minHeight="?actionBarSize"
- app:leftButtonIcon="@mipmap/icon_back_32px"
- app:showSearchView="false"
- app:myTitle="首頁"
- />
- <WebView
- android:id="@+id/webview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
- </LinearLayout>
4、使用,在必須的地方如同一般的控件去使用就可以了,注意加上自定義屬性的命名空間,一般為auto就可以了。
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <com.nan.cnshop.widget.CNToolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?attr/colorPrimary"
- android:minHeight="?actionBarSize"
- app:leftButtonIcon="@mipmap/icon_back_32px"
- app:showSearchView="false"
- app:myTitle="首頁"
- />
- <WebView
- android:id="@+id/webview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
- </LinearLayout>
代碼當(dāng)中也可以使用了,具體就不再贅述了。
- final CNToolbar toolbar = (CNToolbar) v.findViewById(R.id.toolbar);
- toolbar.setOnLeftButtonClickListener(new CNToolbar.OnLeftButtonClickListener() {
- @Override
- public void onClick() {
- toolbar.setShowSearchView();
- }
- });