Android ToolBar详解

导读

  • Toolbar是android L引入的一个新控件,继承于ViewGroup,用于取代ActionBar,它提供了ActionBar类似的功能,但是更灵活

  • ToolBar不像ActionBar那么固定,Toolbar更像是一般的View元素,可以被放置在view树体系的任意位置,可以应用动画,可以跟着ScrollView滚动,可以与布局中的其他View交互

  • 当然,你还可以用Toolbar替换掉ActionBar,只需调用setSupportActionBar()

  • 为了兼容更多的设备一般我们都是通过AppCompat中的android.support.v7.widget.Toolbar来使用Toolbar

  • 除此以外,ToolBar还支持android:elevation阴影属性


ToolBar中的几大子View

几大子View

注意:

  1. 自定义的子View由于处于title,subTitle和menu之间,如果menu太多,或者Title,subTitle的字体太大或长度太长,自定义的子View可能被挤在中间而显示不出来
  2. 自定义的子View 部分最左边有间隙,如果要去掉,可以设置 contentInset 去掉

> 3. NavigationIcon 和 logo 不建议同时使用,不然logo 和 title,subtitle的间距会显得比较小

ToolBar的使用方式:

  1. 将Toolbar当作actionbar来使用。这种情况一般发生在你想利用actionbar现有的一些功能(比如能够显示菜单中的操作项,响应菜单点击事件,使用ActionBarDrawerToggle等),但是又想获得比actionbar更多的控制权限。

  2. 将Toolbar当作一个独立的控件来使用,这种方式又名Standalone。


ToolBar 使用步骤(独立控件方式):

一.设置主题(主要是为了隐藏ActionBar)

  1. ==常规来说==:直接用 Theme.AppCompat.Light.NoActionBar 即可

  2. 下面的方式主要解决部分项目既用Actionbar又用Toolbar

    • res\values\styles.xml (兼容低版本)
     <!--ToolbarActivity 的Theme-->
    <style name="AppTheme.NoActionBar">
        <!--隐藏ActionBar-->
        <item name="windowActionBar">false</item>
        <!--隐藏Title 标题栏(状态栏)-->
        <item name="windowNoTitle">true</item>

        <!--Title,item字体颜色-->
        <item name="android:textColorPrimary">#f00fff</item>
        <!--窗体背景颜色-->
        <item name="android:windowBackground">@color/colorBackground</item>
        <!--底部操作栏颜色 API>21-->
        <item name="android:navigationBarColor">#33f000</item>
        <!--控件的默认颜色,如复选框未选中时的颜色,本文右上角的溢出菜单-->
        <item name="android:colorControlNormal">#ffffff</item>
    </style>

    <!--ToolbarActivity 弹出menu 的Theme-->
    <style name="AppTheme.menu1">
        <!--字体颜色-->
        <item name="android:textColor">#fff</item>
        <!--字体大小-->
        <item name="android:textSize">18sp</item>
        <!--&lt;!&ndash;背景色&ndash;&gt;-->
        <item name="android:colorBackground">#000</item>
        <!--选中颜色-->
        <item name="android:selectableItemBackground">@drawable/item_selector</item>

        <!-- 是否覆盖锚点,默认为true,即盖住Toolbar -->
        <item name="overlapAnchor">false</item>

    </style>
  • res\values-v21\styles.xml (Android 5.0 的style,兼容高版本)
    <style name="AppTheme" parent="AppTheme.NoActionBar">
    </style>

注意:

  1. “windowActionBar”和”windowNoTitle”在AppCompatActivity中使用
  2. “android:windowActionBar”和”android:windowNoTitle”要在Activity中使用
  3. 主题调用:
    1. 清单文件对应activity便签中调用 android:theme=”@style/AppTheme.NoActionBar”
    2. 全局调用,清单文件Application标签中调用android:theme=”@style/AppTheme.NoActionBar”
    3. 对应控件调用 android:theme=”@style/AppTheme.NoActionBar”

二.设置控件

  1. 在布局xml文件添加ToolBar控件(命名空间设置属性)
<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:clipToPadding="true"
        android:elevation="10dp"
        android:fitsSystemWindows="true"
        app:logo="@mipmap/ic_launcher"
        app:navigationIcon="@mipmap/ic_drawer_home"
        app:popupTheme="@style/AppTheme.menu1"
        app:subtitle="Subtitle"
        app:title="Title"
        >
        <!--自定义的子View-->
        <Button
            android:id="@+id/btn_user"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/colorAccent"
            android:text="@string/controls_toolbar"
            android:textColor="@color/colorBackground"/>
    </android.support.v7.widget.Toolbar>

注意:

ToolBar控件设置属性有两种方式:
- 第二种方式设置了属性,第一种方式会无效
1. 代码方式: (在Activity中初始化控件并设置参数)

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);//设置导航栏图标
        toolbar.setLogo(R.mipmap.ic_launcher);//设置app logo
        toolbar.setTitle("Title");//设置主标题
        toolbar.setSubtitle("Subtitle");//设置子标题
        toolbar.inflateMenu(R.menu.base_toolbar_menu);//设置右上角的填充菜单
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
           ...
            }
        });
  1. 在ToolBar控件上直接设置:

    • 自定义命名空间才能设置成功,不然没反应

      1. 先在根布局设置命名空间: 如 xmlns:app=”http://schemas.android.com/apk/res-auto”

      2. 通过命名空间设置属性:如 app:popupTheme=”@style/AppTheme.NoActionBar” (设置溢出菜单主题)

  1. 在res/menu下 添加action 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="@mipmap/ic_search"
        android:title="@string/search_menu"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_notification"
        android:icon="@mipmap/ic_notifications"
        android:title="@string/notification_menu"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_item1"
        android:title="@string/item1_menu"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_item2"
        android:title="@string/item2_menu"
        app:showAsAction="never" />
</menu>

三.控件调用

/**
 * ToolBar作为独立控件使用
 */
public class ToolBarActivity extends AppCompatActivity {
    private Button  btn;
    private Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();

        initEvent();

    }

    private void initEvent() {
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                int menuItemId = item.getItemId();
                if (menuItemId == R.id.action_search) {
                    Toast.makeText(ToolBarActivity.this, R.string.search_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_notification) {
                    Toast.makeText(ToolBarActivity.this, R.string.notification_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_item1) {
                    Toast.makeText(ToolBarActivity.this, R.string.item1_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_item2) {
                    Toast.makeText(ToolBarActivity.this, R.string.item2_menu, Toast.LENGTH_SHORT).show();

                }
                return true;
            }
        });

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(ToolBarActivity.this, R.string.controls_toolbar, Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * 初始化界面
     */
    private void initView() {
        setContentView(R.layout.activity_toolbar);
        StatusBar.setTransparentStatusBar(this); //设置透明的状态栏
        btn = (Button) findViewById(R.id.btn_user);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.inflateMenu(R.menu.toolbar_menu);//设置右上角的填充菜单(替换ActionBar方式不调用)

    }

效果图:

效果图


ToolBar 使用步骤(替换ActionBar方式):

一.设置主题

 <!--ToolbarActivity2 的Theme-->
    <style name="AppTheme.NoActionBar2">
        <!--隐藏ActionBar-->
        <item name="windowActionBar">false</item>
        <!--隐藏Title 标题栏(状态栏)-->
        <item name="windowNoTitle">true</item>
        <!--Title,item字体颜色-->
        <item name="android:textColorPrimary">#ff0000</item>
        <!--窗体背景颜色-->
        <item name="android:windowBackground">@color/colorAccent</item>
        <!--底部操作栏颜色 API>21-->
        <item name="android:navigationBarColor">#4CAF50</item>
        <!--控件的默认颜色,如复选框未选中时的颜色,本文右上角的溢出菜单-->
        <item name="android:colorControlNormal">#00BCD4</item>

    </style>

二.设置控件

  1. 在布局xml文件添加ToolBar控件
 <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:clipToPadding="true"
        android:elevation="10dp"
        android:fitsSystemWindows="true"
        >
        <!--自定义的子View-->
        <TextView
            android:id="@+id/tv_user2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/controls_toolbar"
            android:textColor="@color/colorBackground"/>
    </android.support.v7.widget.Toolbar>
  1. 在res/menu下 添加action 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="@mipmap/ic_search"
        android:title="@string/search_menu"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_notification"
        android:icon="@mipmap/ic_notifications"
        android:title="@string/notification_menu"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_item1"
        android:title="@string/item1_menu"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_item2"
        android:title="@string/item2_menu"
        app:showAsAction="never" />
</menu>

三.控件调用

/**
 * 将ToolBar当作actionBar使用
 */
public class ToolBar2Activity extends AppCompatActivity {
    private TextView mTextView;
    private Toolbar  toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();

        initEvent();

    }

    private void initEvent() {
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                int menuItemId = item.getItemId();
                if (menuItemId == R.id.action_search) {
                    Toast.makeText(ToolBar2Activity.this, R.string.search_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_notification) {
                    Toast.makeText(ToolBar2Activity.this, R.string.notification_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_item1) {
                    Toast.makeText(ToolBar2Activity.this, R.string.item1_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_item2) {
                    Toast.makeText(ToolBar2Activity.this, R.string.item2_menu, Toast.LENGTH_SHORT).show();

                }
                return true;
            }
        });

        mTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(ToolBar2Activity.this, R.string.controls_toolbar, Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * 初始化界面
     */
    private void initView() {
        setContentView(R.layout.activity_toolbar2);
        StatusBar.setTransparentStatusBar(this); //设置透明的状态栏
        mTextView = (TextView) findViewById(R.id.tv_user2);
        toolbar = (Toolbar) findViewById(R.id.toolbar2);
        toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);//设置导航栏图标
        toolbar.setLogo(R.mipmap.ic_launcher);//设置app logo
        toolbar.setTitle("Title");//设置主标题
        toolbar.setSubtitle("Subtitle");//设置子标题

        setSupportActionBar(toolbar);
    }

    /**
     * ToolBar 替换ActionBar 方式要用这种方式实现Menu布局,不然没效果
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater=getMenuInflater();
        inflater.inflate(R.menu.toolbar_menu,menu);
        return super.onCreateOptionsMenu(menu);
    }
}

效果图:

效果图


Theme小扩展:

关于theme中几个color字段的官方描述图:

image

属性 说明
colorPrimary 应用的主色调,ActionBar默认使用该颜色,ToolBar导航栏的底色
colorPrimaryDark 应用的主要暗色调,StatusBar状态栏默认使用改颜色
colorAccent 控件选中的默认颜色,如EditText 的闪动光标
android:colorControlNormal 控件未选中时的默认颜色,如复选框
android:textColorPrimary 应用的主要文字颜色,ActionBar的标题文字默认颜色
android:textColorSecondary 辅助的文字颜色,一般比textColorPrimary的颜色弱一点,用于一些弱化的表示
android:windowBackground 窗体背景颜色,必须用color.xml定义的颜色
android:navigationBarColor 底部操作栏颜色 API>21
扩展属性 扩展说明
statusBarColor 状态栏颜色,默认使用colorPrimaryDark
colorForeground 应用的前景色,ListView的分割线,switch滑动区默认使用该颜色
colorBackground 应用的背景色,popMenu的背景默认使用该颜色
colorControlHighlight 控件按压时的色调
colorControlActivated 控件选中时的颜色,默认使用colorAccent
colorButtonNormal 默认按钮的背景颜色
editTextColor 默认EditView输入框字体的颜色。
textColor Button,textView的文字颜色
textColorPrimaryDisableOnly RadioButton,checkbox等控件的文字
colorSwitchThumbNormal switch thumbs 默认状态的颜色. (switch off)
 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!--对应ActionBar颜色-->
        <item name="colorPrimary">@color/colorPrimaryDark</item>
        <!--对应状态栏颜色-->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <!--对应EditText 光标 颜色-->
        <item name="colorAccent">@color/colorAccent</item>
        <!--Title,item字体颜色-->
        <item name="android:textColorPrimary">#f00fff</item>
        <!--窗体背景颜色-->
        <item name="android:windowBackground">@color/colorBackground</item>
        <!--底部操作栏颜色 API>21-->
        <item name="android:navigationBarColor">#33f000</item>
        <!--控件的默认颜色,如复选框未选中时的颜色,本文右上角的溢出菜单-->
        <item name="android:colorControlNormal">#ffffff</item>
    </style>

测试效果图:

image


源码地址:

源码下载


总结:

  1. 这次的学习,发现Theme和menu的理解有限,后续学习后文章补充这块内容
  2. 测试的时候,发现6.0系统 selectableItemBackground设置Menu点击背景颜色 没反应,有解决方案的评论告知,谢了

样式与主题详解


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章