MeterialDesign系列文章(一)ToolBar的使用

6,972 阅读12分钟

在Android5.0最引人注意的就是MaterialDesign设计风格了,百度百科是这么解释MaterialDesign 的!只能说自己懒,一直没有研究这个东西,但我发现这个东西其实在交互上真的比之前那种交互好了很多,所以我觉得有必要去学习一下这个东西。网上很多相关的内容,但是我觉得,网上的东西再好,写的在牛逼,自己不去尝试、不去总结都是白搭。一点意义的没有,所以这里自己决定总结一下,把中间的踩坑经历和大家分享一下。

这里奉劝各位看官大人,不管什么文章。写的再好再烂也是人家的,不是自己的。写代码就是这样不断的练习、不断的学习。才能在这个知识不断迭代的时代,不被社会淘汰!

请开始你的表演

Android中MaterialDesign开发(一)ToolBar的使用

  • Toolbar的展示
  • Toolbar的进阶使用
  • Toolbar的一些常见案例实现
  • Toolbar的一些问题集锦

1.Toolbar的展示

其实对于Toolbar要求不高的话,展示是很简单的直接在布局中添加就好了。像下面这样

  • 修改主题样式

        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
        </style>
        
        <!--Toolbar主题的设置,Application使用的是这个主题-->
            <style name="BaseTheme" parent="AppTheme">
            <item name="windowActionBar">false</item>
            <item name="windowNoTitle">true</item>
    </style>
    
  • 设置ToolBar

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout 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"
        tools:context="com.jinlong.newmaterialdesign.MainActivity">
    
        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimaryDark"
            app:navigationIcon="@mipmap/back_icon"
            app:title="ToolBar的展示"
            app:titleTextColor="@android:color/white" />
    
    </android.support.constraint.ConstraintLayout>
    
    

Toolbar最简单的展示

这里面有一些常用属性简单介绍一下:

  • android:background 设置背景色
  • app:navigationIcon 返回按钮的图标(其实这里不光可以设置返回按钮,还可以设置别的图标)这个是由默认图标的?attr/homeAsUpIndicator
  • app:title 显示的标题
  • app:titleTextColor 标题的颜色
  • app:subtitle 副标题
  • app:subtitleTextColor 副标题颜色
  • app:logo Logo的显示

全部设置后是这个样子的。这里唠叨一句,其实ToolBar不是只能设置到顶上了,只要你想,设置到哪里都是可以的!

全部设置后的样子

2.Toolbar的进阶使用

每次我看到细节这个词的时候,就会啰嗦很久,很久。。。

2.1在初始化Toolbar的时候要注意

ToolBar的版本

这里要导入v7下的包(新版本的)!这里你要是导入的是widger的话,可能有的API会有些出入的!关于ActionBar的使用就不再这里讲解了。

2.2Toolbar和ActionBar的关联问题

或许在之前的项目中你会看见ActionBar的影子,这是因为之前实现这种标题都使用的是ActionBar,但是后来在5.0的时候Toolbar替代了ActionBar。

setSupportActionBar(Toolbar toolbar);//向下兼容的版本可以使用,注意这里设置的是v7包下的Toolbar
setActionBar(Toolbar toolbar);//21版本才能使用的方法,注意这里设置的是widget包下的Toolbar

如果你不关联ActionBar的时候是没有办法使用menu的!!!所以你想使用menu的时候就必须关联ActionBar。

2.3Toolbar标题的居中

这里就看你对Toolbar是否了解了,其实Toolbar是一个继承ViewGroup的控件,这就说明它是可以有内部控件的!这说明了什么呢?说明标题的居中很简单,直接在内部添加一个TextView当作标题就可以了!

```
<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimaryDark"
        app:navigationIcon="@mipmap/back_icon"
        app:subtitleTextColor="@color/colorAccent"
        app:titleTextColor="@android:color/white">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="Toolbar的使用"
            android:textColor="@android:color/white"
            android:textSize="20sp" />
    </android.support.v7.widget.Toolbar>
```

标题居中的样子

这里有一个注意点:当你关联了ActionBar的时候,会出现两个标题,像变成这样了!

关联了ActionBar的样子

解决办法有两种:

  • 不关联ActionBar(但是就没有办法使用menu了)
  • 在setSupportActionBar()/setActionBar()之前调用toolbar.setTitle("")方法进行解决

这样界面就能恢复到上面那样了,其实之前在这里也踩过坑!!!所以我在上面说,关联ActionBar会有一些意象不到的现象

2.4相应的menu设置

设置menu其实很简单,但是menu的使用就有很多的问题了。至于menu不清楚的,可以在之后Android中menu的使用集锦中理解关于menu的使用。其实Toolbar集成menu是很简单的,其实就是重写Activity的**boolean onCreateOptionsMenu(Menu menu)**的方法,这个方法返回一个boolean,用来判断你是否创建了相应的menu文件。代码是这样滴。。。

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.menu_main,menu);
        return true;
    }

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/app_bar_search"
        android:icon="@drawable/ic_search_black_24dp"
        android:title="搜索"
        app:actionViewClass="android.widget.SearchView"
        app:showAsAction="ifRoom" />
    <item
        android:icon="@mipmap/ic_directions_bike_white_24dp"
        android:title="骑行"
        app:showAsAction="never" />
    <item
        android:icon="@mipmap/ic_directions_bike_white_24dp"
        android:title="其他"
        app:showAsAction="never" />
</menu>

然而你发现并没有显示出来。。。为什么呢?因为上面和你说过,如果不设置ActionBar是没有办法关联menu文件的!所以你要把代码变成这样!

    private void initToolbar() {
        Toolbar toolbar =findViewById(R.id.toolbar);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.menu_main,menu);
        return true;
    }

**setSupportActionbar(toolbar)**这一行代码千万别忘了,否则是显示不出来的!!!

这里有个问题说一下,toolbar上最多展示一个标题(过长的话,后面会用...代替),一个navigationIcon(返回键),一个logo,最多三个图标(这里包括那三个点) 显示出来是这个样子的!

添加menu后的样子

感觉好丑啊,白的字配上黑色的图标。。。瞬间炸裂。而且你会发现点击右侧的按钮会变成这个样子?纳尼。。。

弹出menu后的样子

如果你们的UI能接受这种样式,那么你们UI该跑路了。。。

2.5修改menu弹出的位置和样式

Toolbar有这样一个属性popupTheme="@style/ToolbarPopupTheme"这个属性是给Toolbar设置主题的!所有的位置,和上面的图片颜色都是基于这个属性进行设置的,那么我们来看看这个主题应该怎么去进行设置!!!

  • 修改弹出框的文字样式、popup背景的样式
        <!--Toolbar的Theme的设置,都是针对popup的设置-->
        <style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
            <item name="android:colorBackground">#223344</item><!--设置背景颜色的-->
            <item name="android:textColorPrimary">@android:color/white</item><!--设置文字颜色的-->
            <item name="android:textSize">16sp</item><!--设置文字大小的-->
        </style>
    

设置好后,千万别忘了设置popupTheme="@style/ToolbarTheme,这样弹出款那个的显示问题我们就解决了。

  • 修改弹出框的位置问题
        <!--Toolbar的Theme的设置,都是针对popup的设置-->
        <style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
            <item name="android:colorBackground">#223344</item><!--设置背景颜色的-->
            <item name="android:textColorPrimary">@android:color/white</item><!--设置文字颜色的-->
            <item name="android:textSize">16sp</item><!--设置文字大小的-->
            <item name="actionOverflowMenuStyle">@style/OverflowMenuTheme</item><!--设置弹出位置的主题-->
        </style>
    
        <!--Toolbar弹出popup主题的设置-->
        <style name="OverflowMenuTheme" parent="Widget.AppCompat.Light.PopupMenu.Overflow">
            <item name="overlapAnchor">false</item><!--这个属性设置为false,就能使得popup在Toolbar的下面显示-->
        </style>
    

这里注意一个问题:actionOverflowMenuStyle这个属性什么版本都可以使用,但是如果你写成android:actionOverflowMenuStyle的话,就变成了只有21版本才能使用的了。

未修改溢出菜单的时候

可以看出,位置文字颜色都改变了,但是这个溢出菜单和搜索那个按钮实在是太丑了。这样我是拒绝的。。。

  • 修改溢出菜单的颜色

    其实修改溢出菜单就要修改相应的主题样式了,记得前面最开始修改的主题把,只要在上面加上<item name="android:textColorSecondary">#ffffff</item>就可以了。然后主题变成了这个样子。。。

        <!--Toolbar主题的设置,Application使用的是这个主题-->
        <style name="BaseTheme" parent="AppTheme">
            <item name="windowActionBar">false</item>
            <item name="windowNoTitle">true</item>
            <item name="android:textColorSecondary">#ffffff</item>
        </style>
    

这样页面就变成了这个样子

总体设置完成后的样子

总算是看着像点样子了。。。但是存在像素眼的UI会说,看为什么右边有个白边。。。我想说大白边很厉害的。。。其实这么设置是有道理的,meterialDesign存在一个层级,这里右边是留给阴影的。但是UI要是说不管。。。好吧我们改!

  • 修改弹出款的右边距

    其实这个东西挺好改的。直接在刚才的主题中添加这么一个属性<item name="android:paddingRight">-5dp</item>这里如果你设置0的时候就像上面那样,但是你要是设置成-5的话,他就乖乖的跑到右边去了。。。主题就变成了!

        <!--Toolbar的Theme的设置,都是针对popup的设置-->
        <style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
            <item name="android:background">#223344</item><!--设置背景颜色的-->
            <item name="android:textColorPrimary">@android:color/white</item><!--设置文字颜色的-->
            <item name="android:textSize">16sp</item><!--设置文字大小的-->
            <item name="actionOverflowMenuStyle">@style/OverflowMenuTheme</item><!--设置弹出位置的主题-->
            <item name="actionOverflowButtonStyle">@style/OverflowTheme</item>
            <item name="android:paddingRight">-5dp</item>
        </style>
    

最终的效果

如果这样美工还不满意,你就让她去死吧!!!

2.6一些相应的监听

设置点击监听分为两种 - 设置ActionBar的监听(这个主要是针对menu的开发内容) - 没有设置ActionBar的监听(这个主要是针对Toolbar内部设置的控件和navigationIcon的监听)

接下来我们就根据上面的内容进行相应的讲解!!!

2.6.1menu的监听

对于menu的监听,基本上都是监听onOptionsItemSelected(MenuItem item)这个方法,具体和onclickListener的监听都类似,像下面这样

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_cycling:
                Toast.makeText(this, "骑行", Toast.LENGTH_SHORT).show();
                break;
            case R.id.menu_other:
                Toast.makeText(this, "其他", Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }

2.6.2navigationIcon(返回的监听)

这里为什么我说是返回呢?因为大部分的应用都会在此处处理返回的逻辑的。google也早就设计好了,所以把nacigationIcon的监听单独到Toolbar身上了。。。

虚拟机录得,效果不算太好

这样点击就能实现相应的menu点击效果了,你可能会问了,为什么搜索那个按钮没有点击效果,不是我没录,而是关于这个搜索按钮里面有很多细节需要讲解,限于篇幅吧!准备在之后单独写一下!会在之后Toolbar之搜索按钮的使用中于大家见面!其实这里还存在一个menu组的概念,这里在之后Android中menu的使用集锦讲到,还请大家关注!

3.Toolbar的一些常见案例实现

最开始看见Toolbar是在知乎上,知乎APP的ToolBar当时觉得很好看,后来因为工作的原因就搁置了。其实也是很简单的。最开是知乎的首页是这个样子的!

知乎首页效果

上面都讲了关于这些的内容,所以这里我就直接贴代码了,请原谅我的懒!!!

  • 首先是布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout 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"
        tools:context="com.jinlong.newmaterialdesign.ZhiHuToolbarActivity">
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbarZhiHu"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimaryDark"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navigationIcon="@mipmap/ic_zhbook_show_directory"
            app:title="首页"
            app:popupTheme="@style/ToolbarTheme"
            app:titleTextColor="@android:color/white" />
    </android.support.constraint.ConstraintLayout>
    
  • 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/menu_search"
            android:icon="@drawable/ic_search_black_24dp"
            android:title="搜索"
            app:actionViewClass="android.widget.SearchView"
            app:showAsAction="ifRoom" />
        <item
            android:id="@+id/menu_cycling"
            android:icon="@mipmap/ic_directions_bike_white_24dp"
            android:title="去知乎的Toolbar"
            app:showAsAction="never" />
        <item
            android:id="@+id/menu_other"
            android:icon="@mipmap/ic_directions_bike_white_24dp"
            android:title="其他"
            app:showAsAction="never" />
    </menu>
    
  • 主页面代码

    public class ZhiHuToolbarActivity extends AppCompatActivity {
    
        private Toolbar mToolbar;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_zhi_hu_toolbar);
    
            setToolBar();
            setToolBarListener();
        }
    
    
        private void setToolBar() {
            mToolbar = findViewById(R.id.toolbarZhiHu);
            setSupportActionBar(mToolbar);
        }
    
        private void setToolBarListener() {
            mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    finish();
                }
            });
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater menuInflater = getMenuInflater();
            menuInflater.inflate(R.menu.menu_zhihu, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                case R.id.menu_delete:
                    Toast.makeText(this, "删除按钮", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.menu_other:
                    Toast.makeText(this, "其他按钮", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.menu_setting:
                    Toast.makeText(this, "设置按钮", Toast.LENGTH_SHORT).show();
                    break;
            }
            return true;
        }
    }
    
  • 主题style

    <!--Toolbar的Theme的设置,都是针对popup的设置-->
    <style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:background">#223344</item><!--设置背景颜色的-->
        <item name="android:textColorPrimary">@android:color/white</item><!--设置文字颜色的-->
        <item name="android:textSize">16sp</item><!--设置文字大小的-->
        <item name="actionOverflowMenuStyle">@style/OverflowMenuTheme</item><!--设置弹出位置的主题-->
        <item name="android:paddingRight">-5dp</item>
    </style>

    <!--Toolbar弹出popup主题的设置-->
    <style name="OverflowMenuTheme" parent="Widget.AppCompat.Light.PopupMenu.Overflow">
        <item name="overlapAnchor">false</item><!--这个属性设置为false,就能使得popup在Toolbar的下面显示-->
    </style>

4.Toolbar的一些问题集锦

  • menu的长按事件

    有的童鞋可能会发现,menu长按会弹出一个Toast十分的影响美观,这里教大家去掉他!直接将title设置成空串就可以了!

  • navigationIcon和Title的距离问题

    在24版本navigationIcon和Title的距离很远,看着不是很美观。怎么解决呢?当然是拉近彼此的距离了!!!

        <!--navigationIcon和Title的距离问题-->
        <style name="NoSpaceActionBarTheme" parent="Base.Widget.AppCompat.Toolbar">
            <item name="contentInsetStart">0dp</item>
            <item name="contentInsetStartWithNavigation">0dp</item>
        </style>
    

    上面两个控制的距离是一样的!!!然后经这个style加到相应的基类主题中去,像下面这样(根据contentInsetStart值就能控制之间的距离了):

            <!--Toolbar主题的设置-->
            <style name="BaseTheme" parent="AppTheme">
                <item name="windowActionBar">false</item>
                <item name="windowNoTitle">true</item>
                <item name="android:textColorSecondary">#ffffff</item>
                <item name="toolbarStyle">@style/NoSpaceActionBarTheme</item>
            </style>
    

上面基本上涵盖了Toolbar的使用,如果有什么遗漏的问题,还请广大童鞋指出,我及时添加上去。本来我还想写一个和网易云音乐类似的Toolbar来的,但是因为涉及到SearchView,所以会在之后的Toolbar之搜索按钮的使用中进行讲解!希望感兴趣的童鞋到时候不要错过。。。

欢迎关注我的公众号