Android知识Android开发Android技术知识

什么是ToolBar?

2017-06-01  本文已影响4068人  程序员丶星霖

一、简介

Android3.0之后,Google引入了ActionBar,想要统一安卓应用的导航栏样式。但是由于ActionBar难以定制,很大程度上限制了开发人员。较为常见的实现是使用普通的ViewGroup来封装自己的APP Bar,或者使用JakeWharton大神的ActionBarSherlock库。

自2014年Google I/O上Material Design横空出世后,市场上的应用又逐步趋向了样式的风格统一,support library中很快就出来了ToolBar控件,一个定制化的ViewGroup,来完善ActionBar的使用。

ToolBar是ActionBar的替代品,对于像我这样的菜鸟级Android开发者来说,对怎样使用ToolBar还是感到比较困惑,那今天就来学一下如何使用吧。

1.1去掉默认的ActionBar

在styles.xml中新建一个主题AppTheme.Base:

<style name="AppTheme.Base" 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>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

并将这个style应用到application中,这样就可以去除掉所有Activity中默认的ActionBar了。

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme.Base">
</application>
1.2修改ToolBar默认的文字颜色

在styles.xml中新建相应的style:

<style name="AppTheme.Toolbar">
        <!--这个是API21以后才有的属性-->
        <item name="android:colorControlNormal">@color/controlNormal</item>
        <item name="android:textColorPrimary">@color/toolbarColor</item>
    </style>

    <style name="AppTheme.Toolbar.Popup">
        <item name="android:textColorPrimary">@android:color/black</item>
    </style>

然后将style应用到ToolBar上(注意在builde.gradle文件中添加support.v7包的依赖:compile ‘com.android.support:appcompat-v7:24.2.1’)

<android.support.v7.widget.Toolbar
        android:id="@+id/tl_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        app:theme="@style/AppTheme.Toolbar"
        app:popupTheme="@style/AppTheme.Toolbar.Popup"
        app:elevation="4dp">
    </android.support.v7.widget.Toolbar>
1.3如何加上返回按钮并实现返回:导航返回按钮的图标,还可以通过.setNavigationOnClickListener()方法或者app:navigationIcon属性来修改。
//设置ToolBar
private void setupToolBar() {
    setSupportActionBar(mTlBar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);//启动返回按钮
}
   //实现返回功能
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home: //android.R.id.home是Android内置home按钮的id
                finish();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

二、Options Menu的用法

2.1与ActionBar的用法一致在res/menu目录下新建一个search.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"
        android:title="搜索"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="collapseActionView"
        />
</menu>
2.2在Activity中添加ToolBar对应的Menu Item,并设置点击事件:
//为ToolBar添加Menu Item
Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search, menu);
    return super.onCreateOptionsMenu(menu);
}
//实现ToolBar的点击事件
Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home: //android.R.id.home是Android内置home按钮的id
            finish();
            break;
        case R.id.search://搜索Item的ID
            Toast.makeText(this, "你要搜索啥??", Toast.LENGTH_SHORT).show();
            break;
    }
    return super.onOptionsItemSelected(item);
}
2.3如果溢出按钮的颜色与主题色不一样,可以通过修改ToolBar的theme和popupTheme属性来改变。
<android.support.v7.widget.Toolbar
    android:id="@+id/tl_bar"
    app:elevation="4dp"
    app:popupTheme="@style/AppTheme.Toolbar.Popup"
    app:theme="@style/AppTheme.Toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/colorPrimary">
</android.support.v7.widget.Toolbar>

也可以使用theme中的actionMenuTextColor属性设置Menu Item的字体颜色。

<item name="android:actionMenuTextColor">@android:color/black</item>

一般情况下,都是将ToolBar相关的属性集中卸载一个style中。

<style name="AppTheme.Toolbar.Popup" >
    <!--设置menu菜单的背景色-->
    <item name="android:itemBackground">@color/homeTabText</item>
    <!--设置Menu菜单的字体颜色-->
    <item name="android:textColorPrimary">@android:color/black</item>
    <!--设置Menu窗口不覆盖ToolBar视图-->
    <item name="overlapAnchor">false</item>
</style>
2.4也可以在Java代码中也可以获取Menu Item对象,然后通过如下方法设置Item的显示与隐藏:
 //获取Menu Item
MenuItem item = menu.findItem(R.id.search);
//设置Menu Item隐藏
item.setVisible(false);
 //清除所有MenuItem
menu.clear();

三、ActionMenuView

ToolBar默认是将Menu内容显示在右边的,那么怎样可以将其显示在左边或者中间呢?不妨试试ActionMenuView。
ActionMenuView是将原来位于ToolBar中的Menu内容移到自己的名下,将一系列的Menu Item包括在其中,再将其搁置于ToolBar容器中。这样可以更方便的管理和显示Menu内容。所以原本独立的ToolBar控件,就有了一个Child。

3.1将Menu显示在ToolBar中间
<android.support.v7.widget.Toolbar
        android:id="@+id/tl_bar"
        app:elevation="4dp"
        app:popupTheme="@style/AppTheme.Toolbar.Popup"
        app:theme="@style/AppTheme.Toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary">
        <android.support.v7.widget.ActionMenuView
            android:id="@+id/amv_search"
            android:gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

        </android.support.v7.widget.ActionMenuView>
    </android.support.v7.widget.Toolbar>
3.2在Activity中,将Menu资源文件加载到ActionMenuView对象中去:
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search, mAmvSearch.getMenu());
    return super.onCreateOptionsMenu(menu);
}
3.3Menu Item的点击事件方法不需要改动,只需要将ActionMenu对象的点击事件设置转移就可以了:
mAmvSearch.setOnMenuItemClickListener(new ActionMenuView.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                return onOptionsItemSelected(item);
            }
        });
3.4也可以利用getMenu()方法获取到Menu对象,动态添加或删除Menu Item,甚至加载另外一个Menu资源文件:
mAmvSearch.getMenu().clear();
getMenuInflater().inflate(R.menu.search, mAmvOther.getMenu());
3.5还可以利用ActionMenuView控制Menu Item的位置。
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:actionButtonStyle">@style/MyActionButtonStyle</item>
</style>
<style name="MyActionButtonStyle" parent="@android:style/Widget.Holo.ActionBar">
    <!--设置Menu Item的宽度-->
    <item name="android:minWidth">72dip</item>
    <!--设置Menu Item的padding值-->
    <item name="android:padding">0dp</item>
</style>
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.option_walk:
            item.getIcon().setColorFilter(ContextCompat.getColor(this,
                    android.R.color.darker_gray), PorterDuff.Mode.MULTIPLY);
            break;
    }
    return super.onOptionsItemSelected(item);
}

四、actionLayout

通常情况下,ToolBar中的Menu Item只显示为一个Icon,通过标签定义title和icon属性即可。当然也有一些特殊情况,需要自定义Menu Item的内容,常见的就是搜索页面。

4.1定义一个layout文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <EditText
        android:id="@+id/et_search"
        android:hint="搜索你想要的"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>
4.2通过actionLayout属性引入到标签中
<?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"
        android:title="搜索"
        app:actionLayout="@layout/menu_search"
        app:showAsAction="always"
        />
</menu>
4.3注意事项

五、ToolBar Shadow

根据Material Design设计规范,ToolBar是存在于页面Content之上的,有一个类似阴影效果的视觉差。

但是,无论是android:elevation属性,还是使用APPBarLayout包裹ToolBar,都只能兼容5.0及以上版本的系统。要想兼容一下的版本,就必须要自己实现阴影效果。

自己实现阴影效果有两种选择:

5.1新建xml阴影形状,res/drawable/shadow.xml文件
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:startColor="@android:color/transparent"
        android:endColor="#40000000"
        android:angle="90" />
</shape>
5.2和ToolBar一起使用
<LinearLayout 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="wrap_content"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/tl_bar"
        app:elevation="4dp"
        app:popupTheme="@style/AppTheme.Toolbar.Popup"
        app:theme="@style/AppTheme.Toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="4dp"
        android:background="@drawable/shadow" />

</LinearLayout>

为了保持不同设备APP体验的一致性,推荐使用这种方式来实现ToolBar阴影效果。

六、标题居中

ToolBar就是一个定制化的ViewGroup,所以可以在ToolBar里面放置一个TextView控件作为居中的标题来使用,再将ToolBar的Title隐藏起来即可实现ToolBar标题居中的效果。

 <android.support.v7.widget.Toolbar
        android:id="@+id/tl_bar"
        app:elevation="4dp"
        app:popupTheme="@style/AppTheme.Toolbar.Popup"
        app:theme="@style/AppTheme.Toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary">
        <TextView
            android:id="@+id/amv_search"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="标题"
            style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
        </TextView>
    </android.support.v7.widget.Toolbar>

TextView设置了style属性,与ActionBar.Title保持一致,然后还要去掉ToolBar中自有的Title,在布局中使用的app:title=""就不会起作用了,会显示ActionBar的标题。隐藏ActionBar的标题的代码如下:

getSupportActionBar().setDisplayShowTitleEnabled(false);//设置不显示Title

七、Fragment中使用

有的时候,还需要在Fragment中使用ToolBar,比如Activity中不同的Tab显示不同的Fragment,同时每个Tab的ToolBar标题、Menu均不同,这时在Activity中使用同一个ToolBar就相当不方便了。我们可以在每个Fragment的布局中添加各自的ToolBar,然后在Fragment中单独控制。

与Activity中使用ToolBar有所不同的是,替换ActionBar时,需要给setSupportActionBar方法添加作用对象:

((AppCompatActivity)getActivity()).setSupportActionBar((Toolbar) mContentView.findViewById(R.id.tb_toolbar));

八、仿知乎主界面的实现

为了加深对ToolBar的理解,来使用ToolBar来实现知乎主页的效果。

1.xml布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <android.support.v7.widget.Toolbar
        android:id="@+id/tl_bar"
        app:elevation="4dp"
        app:popupTheme="@style/AppTheme.Toolbar.Popup"
        app:theme="@style/AppTheme.Toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary">

    </android.support.v7.widget.Toolbar>

</LinearLayout>
2.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/action_search"
        android:icon="@drawable/ic_search_white_24dp"
        android:title="搜索"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_notification"
        android:icon="@drawable/ic_notifications_active_white_24dp"
        android:title="通知"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="设置"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_about"
        android:orderInCategory="101"
        android:title="关于"
        app:showAsAction="never" />

</menu>
3.style
<style name="AppTheme.Toolbar">
    <!--这个是API21以后才有的属性-->
    <item name="android:colorControlNormal">@color/controlNormal</item>
    <item name="android:textColorPrimary">@color/toolbarColor</item>
</style>

<style name="AppTheme.Toolbar.Popup" >
    <!--设置menu菜单的背景色-->
    <item name="android:itemBackground">@color/homeTabText</item>
    <!--设置Menu菜单的字体颜色-->
    <item name="android:textColorPrimary">@android:color/black</item>
    <!--设置Menu窗口不覆盖ToolBar视图(true为覆盖ToolBar视图)-->
    <item name="overlapAnchor">false</item>
</style>
4.Activity
public class IOSDetailActivity extends BaseActivity {

    @BindView(R.id.tl_bar)
    Toolbar mTlBar;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ios_detail);
        ButterKnife.bind(this);
        mTlBar.inflateMenu(R.menu.ios_menu);
        mTlBar.setNavigationIcon(R.drawable.ic_list_white_24dp);
        mTlBar.setTitle("首页");
    }
}
5.效果图
ToolBar.jpg
好吧,先到这里吧。以后遇到坑再来填!!!感兴趣的朋友关注我的微信公众号,一起学习吧!
我的微信公众号.jpg
上一篇下一篇

猜你喜欢

热点阅读