Android 標題欄(1)
本文來自網易雲社群
作者:孫有軍
標題欄在每個應用中都有,有各種各樣的標題欄,今天我們就主要來說說標題欄怎麼做,主要內容涉及到自定義標題,ActionBar,Toolbar等知識。
自定義標題
幾年前開發安卓是沒有統一的標題的,每一個頁面都需要自己來佈局標題,如果有多個頁面標題類似,往往就統一編寫出來一個佈局,統一管理和處理,這裡我們來看看怎麼編寫自定義佈局標題,不採用系統提供的,因為有時候有些特定的或者特殊效果的標題,自定義比較方便。
需要注意的是現在的應用基本上都從4.0開始支援,就算是低版本也有surpport包可以使用,因此在使用之前,給該頁面設定為NoActionbar。
佈局
首先我們新建一個title_layout.xml佈局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="56dp" android:background="@color/color_FA5864" android:orientation="vertical" tools:showIn="@layout/activity_custom_title"> <ImageView android:id="@+id/back_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:src="@drawable/actionbar_white_back_icon"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@id/back_icon" android:textColor="@color/white" android:textSize="16sp" tools:text="@string/ask"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="18dp" android:src="@drawable/person_center"/> </RelativeLayout>
上面的佈局都很簡單,就是一個相對佈局,兩邊是圖示,中間一個標題,根據具體需求可以實現更為複雜的效果,這裡我們來說說tools效果。
小技巧
tools:showIn="@layout/activity_custom_title"
因為該title_layout是被其他佈局include引用使用的,因此你在當前介面預覽,只能預覽到當前實現的效果,而如果你添加了tools:showIn屬性,就可以在當前佈局預覽到放置到目標佈局後的效果。
tools:text="@string/ask" 當我們在佈局時,有時可能需要設定文案來預覽實現效果,但是當正式提交時又需要刪除預設設定的文案,這裡可以使用tools:text來插入文案,這個只在編寫時有效果,正式提交時會刪除該屬性。
佈局引用
在佈局完成後,就可以在目標佈局中include使用:
<include layout="@layout/title_layout"></include>
其他設定
最後關掉當前的Actionbar,有以下幾種方式可以關閉:
onCreate中呼叫requestWindowFeature(Window.FEATURE_NO_TITLE);記住一定要在setContentView之前呼叫。至於為什麼,你看看原始碼就知道了。
在AndroidManifest對對應的Activity設定style。style為NoActionBar
如果設定的style不是NoActionBar,則對使用的style複寫<item name="windowActionBar">false</item> 和<item name="windowNoTitle">true</item>屬性
優缺點
自定義很容易實現,他主要有哪些優缺點吶?
優點:
定製度高,靈活 容易實現比較複雜的佈局 容易實現自定義動畫效果
缺點
重複佈局,樣式多時通用性差 很多特定效果,程式碼複雜 系統相比原生,優化比較少
ActionBar & Toolbar
你可能在想為什麼這裡要合在一起,不應該一個一個的講解嗎?這我們先看看他們出現的原因。
歷史沿革
在系統早期沒有統一的標題設定,每個頁面就需要自己來實現標題,因此在Andriod 3.0版本,系統中引入了ActionBar來統一實現標題效果,並且對3.0以前的版本採用support包進行支援(其實現在基本上所有手機已經從4.0開始支援了,因此可以不需要考慮3.0以前的版本),ActionBar的出現,提供了全域性統一的UI介面,並且提供了一致的操作效果,只要你是ActionBar進行實現的,都有同樣的效果。
雖然ActionBar統一了很多東西,但是它也犧牲了靈活性,為了實現某些效果還是需要採用自定義實現,尤其是一些炫酷的標題效果,google也認識到了這個問題,尤其是在當前介面不炫酷都沒有人用的情況下,google在Android L(5.0)版本提供了Toolbar,在L之前的版本採用support包來實現,Toolbar可以當做ActionBar來使用,並且提供了靈活性,因此ActionBar已經不怎麼建議使用了。由於Toolbar可以當前ActionBar來使用,說明兩者具有很多相同的東西,因此這裡放到一起來講解。
ActionBar的顯示與隱藏
ActionBar的顯示
在3.0以上的版本,只要你的Activity實現了Theme.Holo主題,或者Theme.Holo的子主題,他預設就已經有ActionBar效果了。如果是其他主題,你可能需要呼叫requestWindowFeature(Window.FEATURE_ACTION_BAR)函式來顯示,或者對你使用的主題中的 windowActionBar屬性設定為true,而3.0之前的版本(不用考慮3.0之前的版本)你需要讓你的Activity繼承自ActionBarActivity,並且設定主題為Theme.AppCompat主題。
ActionBar的影藏
在前面自定義的時候我們已經說了怎麼隱藏,這裡在來提一下,可以呼叫requestWindowFeature(Window.FEATURE_NO_TITLE)來隱藏,也可以對Activity設定NoActionBar主題進行隱藏,或者設定windowActionBar為false,還可以在程式碼中呼叫getActionBar().hide或者getSupportActionBar().hide()。這裡呼叫的函式不同是根據你繼承的Activity來區分的,如果你直接繼承的是Activity則呼叫getActionBar(),如果是support包中則呼叫getSupportActionBar()。
Toolbar的使用
要使用Toolbar,首先要將默認出現的ActionBar隱藏,因此需要設定NoActionBar,或者設定windowActionBar為false,之後在佈局中加入Toolbar節點。樣例如下,Activity引入的一個toolbar_layout.xml:
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical" tools:context="com.netease.study.ui.title.ToolbarActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="內容內容內容"/> </LinearLayout>
佈局完成後,在介面中find該View,將他設定到ActionBar,讓Activity將它當做ActionBar來處理。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_toolbar); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); }
將find出來的Toolbar設定到ActionBar。就這麼簡單,之後所有的使用方式都跟之前的ActionBar一樣了。從佈局中也可以看出我們將Toolbar放置線上性佈局的頂部,其實它可以放置在任何位置,與ActionBar不一樣,ActionBar預設在頂部,狀態列以下的位置。
設定屬性
既然是標題欄,那肯定是有一些屬性可以進行設定的,那我們就來以此的設定一些屬性,這裡設定的屬性對於ActionBar,Toolbar(這裡的Toolbar是當做ActionBar來使用的,就是呼叫了setSupportActionBar(toolbar)函式)都實用。我們來看看一張圖片,先來認識一下ActionBar上的各個屬性:
為ActionBar圖示,一般為應用圖示,不過現在很多應用已經不再顯示圖示了,包含它只是為了品牌曝光和宣傳;
Action按鈕,點選這些圖示可以做一系統響應Overflow按鈕,當前面的Action按鈕顯示不下,且配置了某些屬性時會顯示該按鈕。
設定圖示
可以採用如下的方式來設定應用圖示:
1. 在AndroidManifest中的Application節點或者Activity節點設定logo屬性
但是要注意的是如果你的主題是Theme.Holo的,如果設定了logo屬性,預設是會顯示圖示的,但是如果你設定的是Theme.AppCompat,那恭喜你,預設不顯示,如果你想顯示怎麼辦程式碼中呼叫。
2.呼叫程式碼來顯示
如果配置中沒有設定logo屬性,我們需要程式碼來控制,但是這裡也分為兩種情況:
a.如果你的Activity是繼承自Activity的,那麼你可以直接呼叫getActionBar().setLogo() b.如果你的Activity是繼承自AppCompatActivity的,那麼你需要如下的方式來進行設定,三個設定方式一個都不能少: private void setLogo() { ActionBar actionBar = getSupportActionBar(); actionBar.setLogo(R.drawable.logo); actionBar.setDisplayUseLogoEnabled(true); actionBar.setDisplayShowHomeEnabled(true); }
上面就是整個設定logo的方式,Android就是這麼的坑爹啊!不同的版本,不同的主題,不同的基類情況就完全不一樣了,這也是Android適配的一方面,全是坑,坑。
設定標題
設定標題是比較簡單的,不會出上面的那些么蛾子,主要有以下兩種方式來設定:
1:在AndroidManifest的Activity設定label節點,但是要注意的是這裡只能設定主標題
2:在程式碼中設定,如果是繼承自Activity呼叫getActionBar().setTitle()來設定主標題,呼叫getActionBar().setSubTitle()來設定副標題。如果是繼承自AppCompatActivity,則需要呼叫getSupportActionBar來進行設定。
設定Action按鈕
我們在上面的ActionBar圖中認識到了有Action按鈕。那怎麼新增Action按鈕吶?
1:首先建立一個選單佈局 action_menu.xml,放置到menu檔案下:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/search_icon" android:icon="@drawable/actionbar_search_dark_icon" android:title="@string/search" app:showAsAction="always"> </item> <item android:id="@+id/plus" android:icon="@drawable/actionbar_plus_icon_normal" android:title="@string/more" app:showAsAction="always"> </item> </menu>
選單裡面包含兩個按鈕一個搜尋,一個加號,每一個item就表示一個選單,item裡面可以繼續巢狀menu,作為該項item的子選單。這裡我們來看看每一個item有哪些屬性需要設定:
id標識該選單
icon 顯示圖示,如果在overflow則顯示title
title 如果在overflow中不顯示icon,直接顯示title,如果在ActionBar長按顯示該title
showAsAction標識顯示規則,重點看一下該屬性:
always: always永遠顯示ActionBar中,如果空間不夠則無法顯示 ifRoom: ifRoom表示有空間的時候顯示在ActionBar中,否則顯示在overflow中 never:never一直顯示在overflow中
同時還需要注意的是:如果你使用的support,也就是Theme為Theme.AppCompat,需要宣告xmlns:app="http://schemas.android.com/apk/res-auto" app可以改成任何名稱,showAsAction前面用app來標識, 如果不是採用的support,也就是Theme為Theme.Holo,前面用android來標識,否則所有選單都預設顯示在overflow中
2:程式碼中載入選單,需要複寫onCreateOptionsMenu函式
@Overridepublic boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.action_menu, menu); return true; }
經過上述兩步,選單就已經顯示在ActionBar上面了。
響應Action按鈕
顯示選單後,需要響應點選事件,怎麼來響應點選事件?需要複寫onOptionsItemSelected函式:
@Overridepublic boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.search_icon: Toast.makeText(this, "clicked", Toast.LENGTH_LONG).show(); break; case R.id.plus: break; } return super.onOptionsItemSelected(item); }
在onOptionsItemSelected中根據id來進行響應。
設定ActionView
我們可以在選單中設定ActionView,比如搜尋,他是一個帶圖示和輸入框的控制元件,他分別有兩種不同的形態,展開和摺疊。接下來我們就講講怎麼設定ActionView。 1.在menu選單的item中設定actionViewClass屬性:
<item android:id="@+id/search_icon" android:icon="@drawable/actionbar_search_dark_icon" android:title="@string/search" app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="ifRoom|collapseActionView"> </item> // 注意 根據是否引用的support包,actionViewClass設定的類不同,如果是support包則設定為android.support.v7.widget.SearchView且用app來標識, 否則設定為android.widget.SearchView且用android來標識
2:在程式碼中可以獲取到ActionView,也可以設定ActionView:
@Overridepublic boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.action_menu, menu); MenuItem search = menu.findItem(R.id.search_icon); // 這種方式也可以獲取到ActionView // SearchView view = (SearchView) search.getActionView(); // 一定要注意匯入的類是否正確,要區分support和非support包中的類 SearchView view = (SearchView) MenuItemCompat.getActionView(search); view.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { return false; } }); return true; }
如果menu選單中沒有設定actionViewClass,也可以在程式碼中手動設定,search.setActionView(new SearchView(this));,上面就是獲取到的SearchView,一定要注意引入的類是否正確,否則會崩潰,拿到後就可以設定查詢等監聽了,這裡就不在演示了。
網易雲免費體驗館,0成本體驗20+款雲產品!
更多網易研發、產品、運營經驗分享請訪問網易雲社群。