总结 Toolbar
基本用法
从 Android 3.0(API level11)开始,所有使用默认主题的 Activity 均使用 ActionBar
作为应用栏。不过,经过不同 Android 版本的演化,应用栏功能已逐渐添加到原生 ActionBar
中。因此,原生 ActionBar
的行为会随设备使用的 Android 系统的版本而发生变化。相比之下,最新功能已添加到支持库版本的 Toolbar
中,并且这些功能可以在任何能够使用该支持库的设备上使用。
因此,您应使用支持库的 Toolbar
类来实现 Activity 的应用栏。使用 support library
的 Toolbar
有助于确保您的应用在最大范围的设备上保持一致的行为。例如,Toolbar
小部件能够在运行 Android 2.1(API 级别 7)或更高版本的设备上提供 Material Design 体验,但除非设备运行的是 Android 5.0(API level 21)或更高版本,否则原生操作栏不会支持 Material Design。
app build.gradle
dependencies {
...
implementation 'com.android.support:appcompat-v7:27.1.1'
}
Toolbar
的 Activity都继承 AppCompatActivity
public class MainActivity extends AppCompatActivity {
}
NoActionBar
主题,这样就不会使用原生的 ActionBar
了。我经常用的就是这个 Theme.AppCompat.Light.NoActionBar
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
xml
布局文件中添加 Toolbar
<?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:orientation="vertical"
tools:context=".MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:elevation="4dp">
</android.support.v7.widget.Toolbar>
</LinearLayout>
Material Design 规范建议应用栏具有 4 dp 的仰角。
5. 在activity中调用 setSupportActionBar()
将 Toolbar
设置为 app bar,并且可以让 Toolbar
使用 ActionBar
的特性。
//将 Toolbar设置为app bar
setSupportActionBar(myToolbar);
//请调用 Activity 的 getSupportActionBar() 方法。此方法将返回对 appcompat ActionBar 对象的引用。
//获得该引用后,您就可以调用任何一个 ActionBar 方法来调整应用栏。例如,要隐藏应用栏,请调用 ActionBar.hide()。
//ActionBar actionBar = getSupportActionBar();
在 res/menu/
文件夹下创建 main_toolbar_menu.xml
<?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">
<!-- about showAsAction
ifRoom: The action will display as a button,if there is enough room in app bar for it.
If there is not enough room, the action will be send to the overflow menu.
never: The action will always listed in the overflow menu.
-->
<item
android:id="@+id/action_serch"
android:icon="@android:drawable/ic_menu_search"
android:title="one"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_call"
android:icon="@android:drawable/ic_menu_call"
android:title="two"
app:showAsAction="never" />
</menu>
如果没有调用 setSupportActionBar()方法 。那么很简单直接用 Toolbar
的 inflateMenu()
方法。
toolbar.inflateMenu(R.menu.main_toolbar_menu.xml);
如果调用了setSupportActionBar()方法。就是将 Toolbar
当做 ActionBar
,所以用如下方法
public class MainActivity extends AppCompatActivity{
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_toorbar_menu, menu);
return true;
}
}
如果没有调用 setSupportAtionBar()
我们要自己来处理menu的点击事件。
toolbar.setOnMenuItemClickListener(
new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// Handle menu item click event
return true;
}
});
把 Toolbar
设置为 ActionBar
,我们处理方式如下
public class MainActivity extends AppCompatActivity{
...
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_serch:
showSnackBar(item.getTitle().toString());
return true;
case R.id.action_call:
showSnackBar(item.getTitle().toString());
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
//弹出一个snackBar
public void showSnackBar(String string) {
Snackbar.make(getDecorView(), string, Snackbar.LENGTH_LONG).show();
}
private View getDecorView() {
return getWindow().getDecorView();
}
}
建议调用 setSupportActionBar()
方法,因为设置了之后,Toolbar
才会有material design效果。
在app bar 左边添加返回键图片,或者其他图片
//使用actionbar自带的返回键图片
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
//使用actionbar,自定义返回键图片
actionBar.setHomeAsUpIndicator(int redId);
//使用toolbar自定义返回键图片
toolbar.setNavigationIcon(int redId);
如果是设置了 setDisplayHomeAsUpEnable(true)
,想改变返回键图片的颜色,可以用如下方法
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!--在主题中 设置 colorControlNomal参数即可改变,返回键的颜色-->
<item name="colorControlNormal">@color/white</item>
</style>
</resources>
//actioBar设置标题
actionBar.setTitle();
//actionBar设置子标题
actionBar.setSubtitle();
//toolbar设置标题
toolbar.setTitle("MaterialDesign");
//toolbar设置标题颜色
toolbar.setTitleTextColor(Color.WHITE);
//toolbar设置子标题
toolbar.setSubtitle("sub title");
//toolbar设置子标题颜色
toolbar.setSubtitleTextColor(Color.BLACK);
设置标题的颜色和字体大小,还可以通过设置 style的方式来设置
<!--主标题-->
<style name="ToolbarTitle" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Title">
<item name="android:textColor">#ffffff</item>
<item name="android:textSize">15sp</item>
</style>
<!--子标题-->
<style name="ToolbarSubtitle" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Subtitle">
<item name="android:textColor">#ffffff</item>
<item name="android:textSize">10sp</item>
</style>
设置完了之后,在布局文件中给 Toolbar
设置对应的style就可以
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:subtitleTextAppearance="@style/ToolbarSubtitle"
app:titleTextAppearance="@style/ToolbarTitle"
android:elevation="4dp">
</android.support.v7.widget.Toolbar>
如果感觉以上的方法设置标题比较麻烦,可以完全定义一个 TextView
当做标题。
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:elevation="4dp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="title"
android:textColor="#FFFFFF"
android:textSize="18sp" />
</android.support.v7.widget.Toolbar>
用此方式设置标题的时候要注意,如果调用了 setSupportActionBar()
方法设置了 Toolbar
,要调用如下方法来禁用使用appNamae来作为默认标题
//actionbar默认会将appName设置为标题,以下是不让actionbar的默认标题展示。我们自已定一个TextView作为标题来维护
actionBar.setDisplayShowTitleEnabled(false);
Toolbar
的action button 只显示图标还可以接受,而overflow menu里面的item 只显示文字有时会让你很难受。那么如何让overflow menu里的item同时显示图标和文字呢。因为系统没有暴露这个方法,我们只能通过反射的方法来解决,如下。
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
if (menu != null) {
if ("MenuBuilder".equalsIgnoreCase(menu.getClass().getSimpleName())) {
try {
@SuppressLint("PrivateApi")
Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
method.setAccessible(true);
method.invoke(menu, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return super.onMenuOpened(featureId, menu);
}
细心的同学还会发现,overflow menu 点开的时候,会覆盖 Toolbar
.解决方法如下
<!--toolbar overflow menu 下拉风格-->
<style name="OverflowMenu" parent="Base.Widget.AppCompat.PopupMenu.Overflow">
<!--下拉框 不是从状态栏开始,而是从toolbar底部开始-->
<item name="overlapAnchor">false</item>
</style>
定义好了style之后,在布局文件里面,给Toolbar设置overflow的style
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="@style/OverflowMenu"
android:elevation="4dp">
</android.support.v7.widget.Toolbar>
最后是加上了返回键,自定义了标题栏,优化了overflow menu之后的效果图
google官方文档 add the app bar
Stack Overflow 关于toolbar.inflateMenu()方法的问题
如果错误,欢迎指正!