Toolbar设置详解----掉坑总结

转载请标明出处:http://www.jianshu.com/p/7b5c99e1cfa3
本文出自:Jlanglang

前言:

因为需要封装toolbar,所以彻底的研究了下toolbar,
以前只是简单用用,现在发现完全用起来很多坑,总结一下.

先来张效果图:

QQ图片20170226164432.png

Toolbar的结构其实很简单:

1.NavigationIcon
2.Logo
3.Title
4.subTitle
5.menu.
常用的:1,3,5

友情提示:

getSupportActionBar()一定要在setSupportActionBar(Toolbar toolbar)之后调用

先说常用的:

1.NavigationIcon的几个方法

//设置是否添加显示NavigationIcon.如果要用
void setDisplayHomeAsUpEnabled(boolean showHomeAsUp);
//设置NavigationIcon的icon.可以是Drawable ,也可以是ResId
void setNavigationIcon(@Nullable Drawable icon);
void setNavigationIcon(@DrawableRes int resId) 
//设置NavigationIcon的点击监听.
void setNavigationOnClickListener(OnClickListener listener);
具体使用:
Toolbar mToolbar =  (Toolbar)findViewById(R.id.toolbar)
//设置Toolbar
 setSupportActionBar(mToolbar);
//显示NavigationIcon,这个方法是ActionBar的方法.Toolbar没有这个方法.
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//设置icon
mToolbar.setNavigationIcon(drawable);
//设置监听.必须在setSupportActionBar()之后调用
mToolbar.setNavigationOnClickListener(clickListener);
总结几个坑:

1.必须先 setSupportActionBar(mToolbar).

2.setDisplayHomeAsUpEnabled(true)是ActionBar的方法.

3.setNavigationOnClickListener()必须要在setSupportActionBar()之后调用才能生效.因为setSupportActionBar(Toolbar),会将Toolbar转换成Acitionbar.点击监听也会重新设置.

2.Title

几个方法:
//是否显示
getSupportActionBar().setDisplayShowTitleEnabled(boolean showTitle);
//设置title.
getSupportActionBar().setTitle(title);
//设置title.
Toolbar.setTitle(title);
//设置Margin边距.
Toolbar.setTitleMargin();
//设置字体.
Toolbar.setTitleTextAppearance();
//设置字的颜色
Toolbar.setTitleTextColor(int color);
总结:

使用比较简单.基本看方法名就知道是干嘛的了.也没什么坑.
Toolbar直接设置title或者getSupportActionBar()再设置title都可以.

3 Menu菜单

这玩意用起来有点蛋疼.坑挺多的.

先说创建:

  @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //写一个menu的资源文件.然后创建就行了.
        getMenuInflater().inflate(R.menu.menu,menu);
        return super.onCreateOptionsMenu(menu);
    }

<menu 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"
      tools:context="com.example.acctionbaractivitydemo.MainActivity">
    <item
        android:id="@+id/menu1"
        //图标
        android:icon="@mipmap/ic_launcher"
        //名字
        android:title=""
        app:showAsAction="withText|ifRoom"/>
    <item
        android:id="@+id/menu2"
        android:icon="@mipmap/ic_launcher"
        android:title="哈哈"
        app:showAsAction="withText"/>
    <item
        android:id="@+id/menu3"
        android:icon="@mipmap/ic_launcher"
        android:title="呵呵"
        app:showAsAction="withText"/>
</menu>

//showAsAction这个属性的值有: 
//1、always:使菜单项一直显示在ToolBar上。 
//2、ifRoom:如果有足够的空间,这个值会使菜单项显示在ToolBar上。 
//3、never:使菜单项永远都不出现在ToolBar上,在…的子项中显示。 
//4、withText:使菜单项和它的图标,菜单文本一起显示。

设置Menu点击

  /**
     * 菜单项被点击时调用,也就是菜单项的监听方法。
     * 通过这几个方法,可以得知,对于Activity,同一时间只能显示和监听一个Menu 对象.
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return super.onOptionsItemSelected(item);
    }
   //通过设置toolbar进行监听,在setSupportActionBar(Toolbar toolbar)之前设置可能会失 效.
    Toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    return false;
                }
            });

Menu的一些操作

 /**
     * 每次菜单被关闭时调用.
     *菜单被关闭有三种情形:
     *1.展开menu的按钮被再次点击
     *2.back按钮被点击
     *3.用户选择了某一个菜单项
     */
    @Override
    public void onOptionsMenuClosed(Menu menu) {
        super.onOptionsMenuClosed(menu);
    }
  /**
     * 在onCreateOptionsMenu执行后,菜单被显示前调用;如果菜单已经被创建,则在菜单显示前被调用。 同样的,
     * 返回true则显示该menu,false 则不显示; (可以通过此方法动态的改变菜单的状态,比如加载不同的菜单等)
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        return super.onPrepareOptionsMenu(menu);
    }
  /**
     * 显示menu的icon,通过反射,设置Menu的icon显示.
     * @param view
     * @param menu
     * @return
     */
    @Override
    protected boolean onPrepareOptionsPanel(View view, Menu menu) {
        if (menu != null) {
            if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
                try{
                    Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    m.setAccessible(true);
                    m.invoke(menu, true);
                } catch (Exception e) {
                    Log.e(getClass().getSimpleName(), "onMenuOpened...unable to set icons for overflow menu", e);
                }
            }
        }
        return super.onPrepareOptionsPanel(view, menu);
    }

style的配置:

style的配置感觉挺恶心的.坑挺多的

基本的配置:

 <style name="toolbar">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        //设置toolbar的最小高度.这样设置的意义,就是解决适配的问题,标准md高度.
        <item name="android:minHeight">?attr/actionBarSize</item>
        <item name="android:background">@color/colorPrimary</item>
          //设置沉浸式,
        <item name="android:fitsSystemWindows">true</item>
    </style>

style的有些方法必须是Sdk21以上才能用,所以得这样

QQ图片20170227110814.png

创建一个values-v21的文件夹,再写一个style.
还得做一些配置.
普通values中的style改成如下:

 <style name="toolbar">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:minHeight">?attr/actionBarSize</item>
        <item name="android:background">@color/colorPrimary</item>

        <item name="android:fitsSystemWindows">true</item>
    </style>
    <style name="base_toolbar" parent="toolbar"/>

values-v21中的style如下:

 <style name="base_toolbar" parent="@style/toolbar">
        <item name="android:elevation">3dp</item>
        <item name="android:navigationIcon">?attr/homeAsUpIndicator</item>
    </style>

使用这个style

   style="@style/base_toolbar"

-----------------------------------------------分割线 -----------------------------------------------

现在来说说style中的坑:
1.app:theme ------------------toolbar的主题
2.app:popupTheme------------弹出的menu的主题.
   <!-- ToolBar样式 .-->
    <style name="toolbar_theme" parent="@style/ThemeOverlay.AppCompat.Dark">
        <item name="android:textSize">18sp</item> <!--  字体大小-->
    </style>
  <!-- ToolBar菜单样式.-->
    <style name="popup_theme" parent="@style/ThemeOverlay.AppCompat.Dark">
        <item name="android:background">@android:color/white</item>
        <item name="android:textColor">@android:color/holo_red_dark</item>
    </style>
继承的是ThemeOverlay.AppCompat:

如果使用的是Dark系列的主题,那么字体就是白色的.menu菜单背景是黑色

Paste_Image.png

如果使用的是Light系列的主题,那么字体和图标就是黑色的.menu菜单背景是白色

Paste_Image.png

下面说说这里坑的地方:

1.修改toolbar的字体
<!-- ToolBar样式 .-->
   <style name="toolbar_theme" parent="@style/ThemeOverlay.AppCompat.Light">
        <!--修改toolbar的Title颜色.正确-->
       <item name="android:textColorPrimary">@android:color/holo_red_dark</item>
       <!--错误,网上有些资料是这样的,然而这样写编译都会报错-->
       <item name="textColorPrimary">@android:color/holo_red_dark</item>
       <!--修改toolbar的subtitle(小标题)颜色.正确-->
       <item name="subtitleTextColor">@android:color/holo_red_dark</item>
   </style>
2.修改Toolbar的menu折叠图标和NavigationIcon的颜色
<style name="toolbar_theme" parent="@style/ThemeOverlay.AppCompat.Light">
          <!-正确,这个要求Api大于21-->
        <item name="android:colorControlNormal">@android:color/holo_red_dark</item>
        <!--这个也正确,用这个吧-->
        <item name="colorControlNormal">@android:color/holo_red_dark</item>
    </style>

效果图:

Paste_Image.png
3.修改menu的字体颜色(大坑):

既然是menu菜单的内容,当然是修改popup_theme了.

找了很多资料,发现都不正确.
比如说设置android:actionMenuTextColor这个属性

 <style name="popup_theme" parent="@style/ThemeOverlay.AppCompat.Light">
        <!--这个不对,不生效-->    
      <item name="android:actionMenuTextColor">@android:color/holo_red_dark</item>
    
    </style>

后来干脆一个个属性试好了,发现其实没那么麻烦..

  <!-- ToolBar菜单样式.-->
    <style name="popup_theme" parent="@style/ThemeOverlay.AppCompat.Light">
      <!--设置背景-->
       <item name="android:background">@android:color/white</item>
       <!--设置字体颜色-->
      <item name="android:textColor">@android:color/holo_red_dark</item>
    </style>

效果:

Paste_Image.png
4.menu菜单的显示位置

默认是这样的:


会遮盖toolbar

可以修改popuptheme的这个属性来设置:

  <!--设置不覆盖锚点-->
   <item name="overlapAnchor">false</item>

有些资料说要这么设置:

    <!-- ToolBar菜单样式.-->
 <style name="popup_theme" parent="@style/ThemeOverlay.AppCompat.Light">
        <item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>
 </style>
 <style name="OverflowMenuStyle"parent="Widget.AppCompat.Light.PopupMenu.Overflow">
        <!--设置不覆盖锚点-->
        <item name="overlapAnchor">false</item>
 </style>

其实没必要,可以直接在app:popupTheme的style里面设置overlapAnchor这个属性就好了.
但是,一定是要在app:popupTheme的style里面设置,而不是app:theme的style里面设置.

最终效果如下:

Paste_Image.png

最终效果的style代码:

    <style name="toolbar">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:minHeight">?attr/actionBarSize</item>
        <item name="android:background">@color/colorPrimary</item>
        <item name="android:fitsSystemWindows">true</item>
    </style>
   <style name="base_toolbar" parent="toolbar"/></style>
     <!-- ToolBar样式.-->
    <style name="toolbar_theme" parent="@style/ThemeOverlay.AppCompat.Light">
        <!--修改toolbar的Title(大标题)颜色-->
        <item name="android:textColorPrimary">@android:color/holo_red_dark</item>
        <!--修改toolbar的subtitle(小标题)颜色-->
        <item name="subtitleTextColor">@android:color/holo_red_dark</item>
        <!--修改toolbar的图标颜色.-->
        <item name="colorControlNormal">@android:color/holo_red_dark</item>
    </style>
    <!-- ToolBar菜单样式.-->
    <style name="popup_theme" parent="@style/ThemeOverlay.AppCompat.Light">
        <!--设置背景-->
        <item name="android:background">@android:color/white</item>
        <!--设置字体颜色-->
        <item name="android:textColor">@android:color/holo_red_dark</item>
        <!--设置不覆盖锚点-->
        <item name="overlapAnchor">false</item>
    </style>

values-v21的style的代码:

  <style name="base_toolbar" parent="@style/toolbar">
        <item name="android:elevation">6px</item>
        <item name="android:navigationIcon">?attr/homeAsUpIndicator</item>
    </style>

toolbar布局的代码

<android.support.v7.widget.Toolbar
    android:id="@+id/tl_costom"
    style="@style/base_toolbar"
    app:theme="@style/toolbar_theme"
    app:popupTheme="@style/popup_theme"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
</android.support.v7.widget.Toolbar>
到此一般的基本设置就写完了.

------------------------------------------------------------------------------------------`

2017-6-21更新

fragment使用menu菜单的正确姿势

坑点:

 @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
    }
1.在frgament里面这个方法就是坑爹的
2.即使 setHasOptionsMenu(true); 也不创建,跳个页面返回回来结果有了.
3.但如果是viewpager+多frgament这种.会造成错乱.其他的frgament也会有menu
4.style配置无效!!

正确姿势:

哥直接代码设置还不行嘛.不配置了

以下代码在setSupportActionBar()之前调用

//设置popupstyle.比如是否覆盖描点,背景,字体颜色什么的.必须在inflateMenu()之前设置
 mToolbar.setPopupTheme(R.style.popup_theme);
//用Toolbar创建menu
 mToolbar.inflateMenu(R.menu.main_home_menu);
//拿到Menu 
Menu menu = mToolbar.getMenu();
//下面的这段代码是为了让menu菜单折叠样式时,展开能显示icon图标.不然icon图标不会显示.(感觉很坑)
if (menu != null) {
     if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
           try {
                    MenuBuilder menuBuilder = (MenuBuilder) menu;
                    menuBuilder.setOptionalIconsVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
}


交流群:493180098,这是个很少吹水,交流学习的群.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容