一開始我便很困惑,TitleBar和ActionBar是什麼關係?
我們知道:
ActionBar是在android3.3之後推出使用的
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen"
這意味着TitleBar似乎消失了,取而代之的是ActionBar。不過,既然是ActionBar,那麼就必然支持Action事件,同理可知TitleBar只顯示圖片和文字,不支持事件的,所以,從某種意義上來說,可以認爲ActionBar是TitleBar的升級 。
對於android3.3自定義標題欄流程如下:
一、自定義標題欄顏色和高度
直接在Activity的屬性中定義即可。
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Light">
<item name="android:windowTitleBackgroundStyle">@style/settingsTitleBg</item>
<item name="android:windowTitleSize">40dp</item>
</style>
<style name="settingsTitleBg">
<item name="android:background">#0000ff</item>
</style>
定義標題欄背景色需要使用到Android:windowTitleBackgroundStyle屬性,給這個屬性指定一個style,這裏爲settingsTitleBg,然後在其中指定android:background的顏色即可。
指定標題欄高度只需要修改android:windowTitleSize的值即可。
二、自定義標題欄佈局
調用如下方法即可:
public static void getCustomTitle(Activity activity, String title) {
mActivity = activity;
mActivity.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
mActivity.setContentView(R.layout.custom_title);
mActivity.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.custom_title);
TextView textView = (TextView) activity.findViewById(R.id.title_content_text);
textView.setText(title);
Button titleBackBtn = (Button) activity.findViewById(R.id.title_back_button);
titleBackBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.d("Title back","key down");
mActivity.finish();
}
});
}
這個方法中使用到了R.layout.custom_title佈局,這個佈局便是可以隨意自定義的佈局文件,這裏指定的佈局文件如下:
custom_title.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:layout_marginLeft="10dp"
android:layout_gravity="center_vertical"
android:background="@drawable/back"
android:id="@+id/title_back_button"
android:layout_width="20dp"
android:layout_height="20dp" />
<TextView
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:id="@+id/title_content_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="20sp"
android:textColor="#FFFFFF"
/>
</LinearLayout>
完成後在setContentView之前調用getCustomTitle方法即可完成自定義標題欄的工作。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//設置全屏
CustomTitle.getCustomTitle(this, "系統信息");
setContentView(R.layout.activity_main);
CustomTitle方法的第一個參數就是當前的Activity,第二個參數是標題欄的標題。CustomTitle是我定義的一個類,其中只有getCustomTitle一個靜態方法。
至此,效果如下:
這裏寫圖片描述
三、Holo主題下自定義標題欄
現在,如果將主題從android:Theme.Light改爲android:Theme.Holo.Light,那麼程序會報錯,如下:
Caused by: android.util.AndroidRuntimeException: You cannot combine custom titles with other title features
這個時候,只需要在style中把ActionBar關掉就好了。
<style name="AppTheme" parent="android:Theme.Holo.Light">
<item name="android:windowTitleBackgroundStyle">@style/settingsTitleBg</item>
<item name="android:windowTitleSize">40dp</item>
<item name="android:windowActionBar">false</item>
</style>
這樣可以自定義標題欄,但是界面呈現出來會有閃爍,也就是默認的ActionBar會先顯示出來,然後纔是你自定義的標題欄,一次,在Holo主題下,這種方法不可取。
自定義ActionBar
我們也可以傳入自定義的佈局文件給ActionBar,方法如下:
getActionBar().setCustomView(R.layout.custom_title);
R.layout.custom_title就是我們傳入的佈局文件。我們也可以通過findViewById來爲各個View設置監聽器。但這種方式也無法便面閃爍原來ActionBar的問題,這非常討厭。
解決自定義ActionBar閃爍原來ActionBar的問題
從原題產生的原因分析,應該是設置主題的時候造成的,主題中如果有ActionBar,那麼ActionBar的繪製在Activity的佈局文件繪製之前,因此,會有閃爍的問題出現。因此,我的解決方法是乾脆不用ActionBar,找一個沒有ActionBar的Theme,比如@android:style/Theme.Holo.Light.NoActionBar.Fullscreen。然後,使用ToolBar代替,ToolBar在Activity的佈局文件中,他可以放置在佈局文件的任意位置,就像一個普通的View組件一樣,因此,它的繪製和Activity內容的繪製是一起的。ToolBar使用如下:
<Toolbar
android:id="@+id/toolbar"
android:title="系統設置"
android:navigationIcon="@drawable/back"
android:background="#0000ff"
android:layout_width="match_parent"
android:layout_height="40dp"></Toolbar>
由於ToolBar在Activity的佈局文件中使用,因此非常有靈活性。這裏設置了title-標題,還有導航icon,我們還可以給導航按鈕這隻事件監聽器,比如讓Acitivity結束運行:
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});