上篇博客,粗略的说到了官方对于toolbar的使用,如有不熟悉可去Android中Toolbar(1)http://blog.csdn.net/hj2drf/article/details/61430582

现在聊聊日常开发中的使用:

Toolbar继承ViewGroup是一个容器类,里面可以添加很多子视图组件,

常用的API如下所示:

1)public void setBackgroundColor(int color)  // 设置背景颜色 
2)public void setTitle(CharSequence title)  // 设置主标题    
3)public void setTitleTextColor(@ColorInt int color)  // 设置主标题颜色    
4)public void setSubtitle(CharSequence subtitle)   //  设置副标题    
5)public void setSubtitleTextColor(@ColorInt int color) // 设置副标题颜色    
6)public void setNavigationIcon(@DrawableRes int resId) // 设置导航图标    
7)public void setNavigationOnClickListener(OnClickListener listener) // 设置导航监听事件    
8)public void setLogo(@DrawableRes int resId) // 设置logo图标    
9)public void setTitleTextAppearance(Context context, @StyleRes int resId) // 设置主标题样式    
10)public void setSubtitleTextAppearance(Context context, @StyleRes int resId) // 设置副标题样式   
11)public void inflateMenu(@MenuRes int resId) // 设置actionmenu    
12)public void setOnMenuItemClickListener(OnMenuItemClickListener listener) // 设置菜单点击事

在使用toolbar需要注意:

setSupportActionBar()方法的调用地方

如果setSupportActionBar() 调用的位置太靠前,会使得Toolbar的部分设置没有效果,例如把setSupportActionBar()方法在setTitle方法前调用,Toolbar的title将显示我们的项目名,而不是我所填写的知乎。最好是在Toolbar的所有设置都已经完成后调用setSupportActionBar()方法。

menu的使用

在Toolbar中有一个inflateMenu()的方法,通过该方法可以设置Toolbar上面的OptionsMenu.如果使用了setSupportActionBar(),那么inflateMenu()方法无效,此时需使用重写activity中的onCreateOptionsMenu()方法来创建Menu。相反,如果没调用setSupportActionBar()方法的话,此时是靠inflateMenu()方法来创建Menu

首先从setSupportActionBar()方法说起,这个方法我试过不掉用,也没什么异样(除了对Menu的影响),调用此方法,对ActionBar的设置都会把相应的属性设置到Toolbar上

实例

1)创建一个布局,在其中添加Toolbar,使用v7包下的

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        app:navigationIcon="@drawable/ic_action_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

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

</RelativeLayout>

2)activity需要继承AppCompatActivity,theme设置android:theme=”@styleTheme.AppCompat.NoActionBar”

public class ToolbarActivity extends AppCompatActivity {

    private Toolbar mToolbar;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_toolbar);

        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        //设置背景色
        mToolbar.setBackgroundColor(Color.BLACK);
        //设置主标题
        mToolbar.setTitle("主标题");
        //设置主标题文字颜色
        mToolbar.setTitleTextColor(Color.WHITE);
        //设置主标题统一样式(包括颜色,字体,字号)
        //mToolbar.setTitleTextAppearance(this, R.style.xxx);
        //设置副标题
        mToolbar.setSubtitle("副标题");
        //设置副标题文字颜色
        mToolbar.setSubtitleTextColor(Color.LTGRAY);
        //设置副标题统一样式(包括颜色,字体,字号)
        //mToolbar.setSubtitleTextAppearance(this, R.style.xxx);
        //设置logo
        mToolbar.setLogo(R.mipmap.ic_launcher);
        //设置导航图标,注意布局中设置的话使用app的
        mToolbar.setNavigationIcon(R.drawable.ic_action_name);
        //设置导航图标点击事件
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Snackbar.make(v, "测试信息", Snackbar.LENGTH_SHORT).show();
            }
        });

        //添加menu
        mToolbar.inflateMenu(R.menu.menu_main);
        //设置menu的点击事件
        mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                int menuId = item.getItemId();
                switch (menuId) {
                    case R.id.action_settings:
                        Snackbar.make(mToolbar, "单击setting", Snackbar.LENGTH_SHORT).show();
                        break;
                    case R.id.action_about:
                        Snackbar.make(mToolbar, "单击about", Snackbar.LENGTH_SHORT).show();
                        break;
                    case R.id.action_exit:
                        Snackbar.make(mToolbar, "单击exti", Snackbar.LENGTH_SHORT).show();
                        break;
                }
                return true;
            }
        });
    }
}

3)menu菜单配置文件

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

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

    <item
        android:id="@+id/action_about"
        android:orderInCategory="200"
        app:showAsAction="never"
        android:title="About"/>

    <item
        android:id="@+id/action_exit"
        android:orderInCategory="300"
        app:showAsAction="never"
        android:title="Exit"/>

    <item android:id="@+id/my_search"
        android:title="@string/search_title"
        android:icon="@drawable/ic_open_search"
        app:showAsAction="ifRoom"
        app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

可以看到,我在这里定义了4个item,分别对应setting,about,exit,search,对于item是否直接显示在toolbar上,取决于app:showASAction=”“的值
其中showAsAction属性共有五个值:ifRoom、never、always、withText、collapseActionView,可以混合使用。

ifRoom 会显示在Item中,但是如果已经有4个或者4个以上的Item时会隐藏在溢出列表中。当然个数并不仅仅局限于4个,依据屏幕的宽窄而定

never 永远不会显示。只会在溢出列表中显示,而且只显示标题,所以在定义item的时候,最好把标题都带上。

always 无论是否溢出,总会显示。

withText withText值示意Action bar要显示文本标题。Action bar会尽可能的显示这个标题,但是,如果图标有效并且受到Action bar空间的限制,文本标题有可能显示不全。

collapseActionView 声明了这个操作视窗应该被折叠到一个按钮中,当用户选择这个按钮时,这个操作视窗展开。否则,这个操作视窗在默认的情况下是可见的,并且即便在用于不适用的时候,也要占据操作栏的有效空间。
一般要配合ifRoom一起使用才会有效果。

android:orderInCategory设置menu的优先级,数字越小优先级越高。优先级低的图标在toolbar中menu图标放不下时,自动折叠到最右侧的图标下

特别说一下,search这个item,单击这个item交互是不一样的哦,直接关联了新的空间SerachView

接下来看下效果

下面再说说另一种是用方式:

mToolbar = (Toolbar) findViewById(R.id.toolbar);

setSupportActionBar(mToolbar);

这个时候就需要取代上一种menu的创建方法及单击事件,通过

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int menuId = item.getItemId();
    switch (menuId) {
        case R.id.action_settings:
            Snackbar.make(mToolbar, "单击setting", Snackbar.LENGTH_SHORT).show();
            return true;
        case R.id.action_about:
            Snackbar.make(mToolbar, "单击about", Snackbar.LENGTH_SHORT).show();
            return true;
        case R.id.action_exit:
            Snackbar.make(mToolbar, "单击exti", Snackbar.LENGTH_SHORT).show();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

防止没有Menu按键的手机不显示Menu:

该特性由ViewConfiguration这个类中一个叫做sHasPermanentMenuKey的静态变量控制,系统根据这个变量的值来判断手机有没有物理Menu键的。当然这是一个内部变量,无法直接访问它,可以通过反射的方式修改它的值,让它为false。

 private void setMenuAlwaysShow() {
        try {
            ViewConfiguration config = ViewConfiguration.get(this);
            Field menuKeyField =                          ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
            menuKeyField.setAccessible(true);
            menuKeyField.setBoolean(config, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

此处参考:Android ActionBar完全解析,使用官方推荐的最佳导航栏(上) - 郭霖的专栏 - 博客频道 - CSDN.NET

http://blog.csdn.net/guolin_blog/article/details/18234477

配置Menu的icon图标:

在ToolBar的主题中配置name=”actionOverflowButtonStyle”属性,创建一个主题继承自android:style/Widget.Holo.Light.ActionButton.Overflow,配置name=”android:src”属性:

<style name="Theme.ToolBar.Base" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:textSize">20sp</item>
        <item name="android:textColorPrimary">@color/black_424242</item>
        <!--s设置Menu菜单的背景色-->
        <item name="android:itemBackground">@color/blue_600</item>
        <!--设置menu菜单不遮挡actionbar-->
        <item name="actionOverflowMenuStyle">@style/OverflowMenu</item>
        <!--配置Menu的图标-->
        <item name="actionOverflowButtonStyle">@style/ToolBar.ActionButton.Overflow</item>
</style>
<style name="ToolBar.ActionButton.Overflow" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
        <item name="android:src">@mipmap/ic_menu_more_overflow</item>
</style>

配置Menu菜单的OvweFlow的action:

基本和ActionBar相同

配置OvweFlow中的action文字颜色:

在ToolBar的主题中配置android:textColorPrimary属性

<style name="Theme.ToolBar.Base" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:textSize">20sp</item>
        <item name="android:textColorPrimary">@color/color_red</item>
</style>

或者在Toolbar的 app:popupTheme=”@style/AppTheme.PopupOverlay”主题中配置android:textColorPrimary属性:

 app:popupTheme="@style/AppTheme.PopupOverlay"
 <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light">>
        <item name="android:textColorPrimary">#fff</item>
 </style>

配置OvweFlow中的action背景:

在ToolBar的主题中配置android:itemBackground属性

 <!--s设置Menu菜单的背景色-->
 <item name="android:itemBackground">@color/black_light</item>

配置OvweFlow中的action的宽度:

在Toolbar的popupTheme中设置android:width属性,但是注意Item的宽度有最大最小的限制,超过该限制后显示效果是最大宽度和最小宽度。

  <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light">
        <!--Item的宽度-->
        <item name="android:width">400dp</item>
        <item name="android:textColorPrimary">#fff</item>
  </style>

配置OvweFlow中的action显示icon:

默认情况下OverFlow中只显示文字,但这样不够美观。在Toolbar的popupTheme中设置android:drawableRight android:drawableLeft android:drawableTop android:drawableBottom属性,注意这个设置对所有Item统一生效的,这样也就没有太大的意义。

<!--<item name="android:drawableLeft">@drawable/ic_action_search</item>-->
        <item name="android:drawableRight">@drawable/ic_home_gray_36dp</item>
        <item name="android:drawableTop">@drawable/ic_textsms_gray_36dp</item>

是否显示Icon是由MenuBuilder这个类的setOptionalIconsVisible方法来决定的,该方法不能直接调用,可以反射之。重写boolean onCreatePanelMenu(int featureId, Menu menu)方法,在menu创建的时候调用之。

  @Override
    public boolean onCreatePanelMenu(int featureId, 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) {
                    e.printStackTrace();
                }
            }
        }
        return super.onCreatePanelMenu(featureId, menu);
    }

配置OvweFlow中的action间的分割线:

在Toolbar的popupTheme中设置android:dividerHeight属性,设置高度大于0就能显示分割线,分割线的默认颜色是白色。

1dp
配置ToolBar的Menu不遮挡ToolBar:

Actionbar中的配置方式是:设置actionOverflowMenuStyle的android:overlapAnchor属性为false.这里同样,不过注意是在ToolBar的主题中而不是Activity的主题。

<style name="Theme.ToolBar.Base" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:textSize">20sp</item>
        <item name="android:textColorPrimary">@color/color_red</item>
        <!--s设置Menu菜单的背景色-->
        <item name="android:itemBackground">@color/gray</item>
        <!--设置menu菜单不遮挡actionbar-->
        <item name="actionOverflowMenuStyle">@style/OverflowMenu</item>

    </style>

    <style name="OverflowMenu" parent="Widget.AppCompat.PopupMenu.Overflow">
        <!--兼容Api 21之前的版本 -->
        <item name="overlapAnchor">false</item>
        <!-- Api 21-->
        <item name="android:overlapAnchor">false</item>
    </style>

配置ToolBar的Home图标左侧间隙

在布局中Toolbar控件中配置属性 app:contentInsetStart=”3dp”

app:contentInsetStart=”3dp”
ToolBar的状态栏沉浸效果:

配置ToolBar和系统状态栏背景色一致:必须配置不使用半透明状态栏才可以设置状态栏颜色,需要android4.4(Api Level 19)及以上

  <style name="Theme.MyActivity" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <!--配置是否使用半透明状态栏-->
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:windowTranslucentNavigation">true</item>
        <!--状态栏颜色-->
        <item name="android:statusBarColor">@color/color_0176da</item>
    </style>

设置Toolbar 浮动:

ToolBar 没有提供显示和隐藏的方法,首先调用 setSupportActionBar(toolbar);方法把ToolBar设置为ActionBar,再使用ActionBar的方式显示隐藏

点击屏幕后显示隐藏ToolBar;

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (actionBar == null) {
            actionBar = getSupportActionBar();
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                if (actionBar != null) {
                    if (actionBar.isShowing()) {
                        actionBar.hide();
                    } else {
                        actionBar.show();
                    }
                }
                break;
    }

    return super.onTouchEvent(event);
}

但是这样设置setSupportActionBar(toolbar);之后,如果是直接在ToolBar上设置的Menu的方式;toolbar.inflateMenu(R.menu.base_toolbar_menu);ToolBar上的Menu菜单会消失,这时候需要使用复写方式添加Menu

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.base_toolbar_menu, menu);
        return true;
    }

ToolBar和一个普通控件是一样的,所以浮动效果应该通过布局搞定,设置Toolbar的根布局为相对布局,同时添加一个移动动画

设置Activity的主题:

 <style name="ToolbarActivityTheme" parent="AppTheme">
        <!--启用ActionBar的叠加模式(不生效)-->
        <item name="windowActionBarOverlay">true</item>
        <!--状态栏半透明-->
        <item name="android:windowTranslucentStatus">true</item>
        <!--内容填充到导航栏-->
        <item name="android:windowTranslucentNavigation">true</item>
        <!--设置全屏-->
        <item name="android:windowFullscreen">true</item>
    </style>

添加动画和隐藏效果:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (actionBar == null) {
            actionBar = getSupportActionBar();
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                if (actionBar != null) {
                    if (actionBar.isShowing()) {
                        int height = toolbar.getMeasuredHeight();
                        height = height <= 0 ? 112 : height;
                        startAnimation(-height, new Runnable() {
                            @Override
                            public void run() {
                                actionBar.hide();
                            }
                        });

                    } else {
                        actionBar.show();
                        startAnimation(0, new Runnable() {
                            @Override
                            public void run() {

                            }
                        });

                    }
                }
                break;
    }
    return super.onTouchEvent(event);
}

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void startAnimation(int transY, final Runnable end) {

    ViewPropertyAnimator animator = toolbar.animate().translationY(transY).setDuration(600);
    animator.start();
    animator.setListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {
            end.run();
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
}

配置Activity内容填充到系统状态栏:

这样Activity的整个内容会冲到屏幕顶部,不是导航栏透明

<item name="android:windowTranslucentNavigation">true</item>

ToolBar的navigationIcon一直居上不居中的异常:

排查原因竟然是在Activity中设置ToolBar的主题……哪怕这个主题中什么都不写,这个图标依然会居上,不明白什么原因

 <style name="ToolBarActivityTheme" parent="Theme.AppCompat.Light">
        <!--使用toolbar取消默认的actionbar-->
        <item name="android:windowActionBar">false</item>
        <item name="windowNoTitle">true</item>

        <item name="android:actionBarStyle">@style/TranslucentActionBar</item>
        <!--设置ActionBar的主题-->
        <!--<item name="android:toolbarStyle">@style/ToolBarActivityToolbarTheme</item>-->
        <item name="toolbarStyle">@style/ToolBarActivityToolbarTheme</item>
    </style>
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐