Toolbar详解(二)

来源:互联网 发布:数据管控流程 编辑:程序博客网 时间:2024/06/12 18:44

前言:


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

先来张效果图:

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 ,也可以是ResIdvoid 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);//设置iconmToolbar.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以上才能用,所以得这样



创建一个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>

效果图:


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>

效果:


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里面设置.

最终效果如下:


最终效果的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>

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();                }        }}