Android基础控件之Toolbar

开个头

总结 Toolbar 基本用法

简介

从 Android 3.0(API level11)开始,所有使用默认主题的 Activity 均使用 ActionBar 作为应用栏。不过,经过不同 Android 版本的演化,应用栏功能已逐渐添加到原生 ActionBar 中。因此,原生 ActionBar 的行为会随设备使用的 Android 系统的版本而发生变化。相比之下,最新功能已添加到支持库版本的 Toolbar 中,并且这些功能可以在任何能够使用该支持库的设备上使用。

因此,您应使用支持库的 Toolbar 类来实现 Activity 的应用栏。使用 support libraryToolbar 有助于确保您的应用在最大范围的设备上保持一致的行为。例如,Toolbar 小部件能够在运行 Android 2.1(API 级别 7)或更高版本的设备上提供 Material Design 体验,但除非设备运行的是 Android 5.0(API level 21)或更高版本,否则原生操作栏不会支持 Material Design。

使用Toolbar
  1. 首先导入V7包。现在的AS创建工程的时候,已经默认给我们导入了。
	app build.gradle
	
	dependencies {
	   ...
	    implementation 'com.android.support:appcompat-v7:27.1.1'
	}
  1. 让所有用到 Toolbar 的 Activity都继承 AppCompatActivity
public class MainActivity extends AppCompatActivity {
}
  1. 设置我们应用的主题为 appcompat 里的 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>
  1. 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();

看下效果
在这里插入图片描述
现在只是效果出来,然后我们开始增砖添瓦。

添加action button和overflowmenu
1创建menu文件

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>
2设置menu.xml文件
2.1没调用setSupportAtionBar()

如果没有调用 setSupportActionBar()方法 。那么很简单直接用 ToolbarinflateMenu() 方法。

	toolbar.inflateMenu(R.menu.main_toolbar_menu.xml);
2.2调用了setSupportActionBar()

如果调用了setSupportActionBar()方法。就是将 Toolbar 当做 ActionBar ,所以用如下方法

public class MainActivity extends AppCompatActivity{
	...
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_toorbar_menu, menu);
        return true;
    }
}
3.响应menu点击事件
3.1没调用setSupportAtionBar()

如果没有调用 setSupportAtionBar() 我们要自己来处理menu的点击事件。

toolbar.setOnMenuItemClickListener(
        new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                // Handle menu item click event
                return true;
            }
});
3.2调用了setSupportAtionBar()

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效果。
在这里插入图片描述

细节调整
1.关于返回键

在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>
2.关于标题
	//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);
3.关于overflow menu

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()方法的问题

如果错误,欢迎指正!

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值