Toolbar作为ActionBar与标题居中

Toollbar作为ActionBar很简单,直接获取到Toolbar后调用setSupportActionBar(toolbar);就行了,但是如果整个应用中统一使用Toolbar替代ActionBar的话,最方便的方式肯定是将Toolbar的布局提取出来然后在不同的Activity中直接include,像下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
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="?actionBarSize"
android:background="@null"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/AppTheme">
<TextView
android:id="@+id/toolbar_title"
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</android.support.v7.widget.Toolbar>
1
2
3
4
5
6
7
8
9
10
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.e7live.dreamfuture.activity.MainActivity">
<include layout="@layout/toolbar"/>
...
</LinearLayout>

然后,为了使用方便,在BaseActivity中设置Toolbar为ActionBar:

1
2
3
4
5
6
7
8
9
View v = findViewById(R.id.toolbar);
if (v != null) {
toolbar = (Toolbar) v;
setSupportActionBar(toolbar);
toolbarTitle = (TextView) v.findViewById(R.id.toolbar_title);
if (toolbarTitle != null) {
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
}

但是,在BaseActivity中什么时候调用上面这一段代码呢?一般情况下很多操作会在BaseActivity的onCreate中执行,但一般子类的写法是这样的:

1
2
3
4
5
6
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
}

在BaseActivity的onCreate中还没有设置ContentView,通过findViewById是找不到Toolbar的,而且一般情况下会在Activity的onCreate中设置ActionBar的一些属性,想到的最适合执行这段代码的地方就是在BaseActivity中重载setContentView了。

只需要注意一点,就是在子类的onCreate中对ActionBar的操作要在setContentView之后,一般这个不会有什么问题。

再说下标题居中,前面在toolbar.xml中看到在Toolbar内有一个TextView,是用来作为标题的,在BaseActivity重载的setContentView中也判断了如果存在这个TextView就隐藏掉Toolbar原来的Title,Toolbar是一个ViewGroup,可以很方便地添加ChildView并设置相关属性。

显示标题的TextView有了,原来的标题也被隐藏了,接下来就是怎么给这个作为标题的TextView设置要显示的标题了,当然可以在每个Activity中对这个TextView调用setText,但太麻烦了,我们都很懒的,很多页面的标题也都是写到AndroidManifest中的。其实Activity有一个onTitleChanged的接口,在Activity的onPostCreatesetTitle中都会调用这个方法:

1
2
3
4
5
6
7
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
if (!isChild()) {
mTitleReady = true;
onTitleChanged(getTitle(), getTitleColor());
}
mCalled = true;
}

所以只需要在BaseActivity中重载这个方法就行了,如下所示:

1
2
3
4
5
6
7
@Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
if (toolbarTitle != null) {
toolbarTitle.setText(title);
}
}

通过AndroidManifest指定的Title会自动显示到这个TextView中,不用做任何处理,如果在代码中想改变标题的话,直接调用Activity.setTitle就行了