标題欄在每個應用中都有,有各種各樣的标題欄,今天我們就主要來說說标題欄怎麼做,主要内容涉及到自定義标題,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使用:
其他設定
最後關掉目前的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,需要聲明
app可以改成任何名稱,showAsAction前面用app來辨別, 如果不是采用的support,也就是Theme為Theme.Holo,前面用android來辨別,否則所有菜單都預設顯示在overflow中
xmlns:app="http://schemas.android.com/apk/res-auto"
2:代碼中加載菜單,需要複寫onCreateOptionsMenu函數
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.action_menu, menu);
return true;
}
經過上述兩步,菜單就已經顯示在ActionBar上面了。
響應Action按鈕
顯示菜單後,需要響應點選事件,怎麼來響應點選事件?需要複寫onOptionsItemSelected函數:
@Override
public 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來進行響應。
由于文章是在太長,是以将文章分成了兩篇,剩下的内容在Android 标題欄(二)