MaterialDesign学习篇(二),Toolbar、DrawerLayout的使用

什么是Toolbar

Toolbar是应用的内容的标准工具栏,可以说是Actionbar的升级版,两者不是独立关系,要使用Toolbar还是得跟ActionBar扯上关系的。相比Actionbar,Toolbar最明显的一点就是变得很自由,可随处放置,因为它是作为一个ViewGroup来定义使用的,所以单纯使用ActionBar已经稍显过时了,它的一些方法已被标注过时。

Toolbar提供了一些可定制化修改的属性,这些可定制修改的属性在API文档中都有详细介绍,如:

  • 设置导航栏图标;
  • 设置App的logo;
  • 支持设置标题和子标题;
  • 支持添加一个或多个的自定义控件;
  • 支持Action Menu;

如何使用Toolbar

演示如下:

步骤

一、在res目录中国,创建menu目录,并简历对应的xml文件,可任意命名,此处命名为menu_tool_bar.xml。

menu_tool_bar.xml中的代码:

<?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/menu_search"
        app:showAsAction="ifRoom" />

    <!--右侧添加操作条目-->
    <item
        android:id="@+id/action_add"
        android:icon="@mipmap/ic_add"
        android:title="@string/menu_add"
        app:showAsAction="ifRoom" />

    <!--右侧设置条目,收起,不显示-->
    <item
        android:id="@+id/action_setting"
        android:icon="@mipmap/ic_add"
        android:title="@string/menu_setting"
        app:showAsAction="never" />

    <!--右侧设置帮助条目,收起,不显示-->
    <item
        android:id="@+id/action_help"
        android:icon="@mipmap/ic_add"
        android:title="@string/menu_help"
        app:showAsAction="never" />

</menu>

这里配置的是toolbar右侧一些操作的条目,其中的showAsAction配置菜单项如何显示,有以下的值可选:

  • always:使菜单项一直显示在ToolBar上。
  • ifRoom:如果有足够的空间,这个值会使菜单项显示在ToolBar上。
  • never:使菜单项永远都不出现在ToolBar上,在竖立的三点水(更多)图标的子项中显示。
  • withText:使菜单项和它的图标,菜单文本一起显示。

我们设置了搜索和添加的菜单项showAsAction指定为ifRoom,在有足够的空间,它们是展示出来的,将设置和帮助的菜单项的showAsAction指定为never,所以它们就收起不显示,点击"更多"的图标的时候,它们才会显示。

二、布局文件中,使用Toolbar

在对应布局的xml文件中,配置toolbar:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        >

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

由于Toolbar是在 Android 5.0才开始有的,我们需要在工程中引入 appcompat-v7的兼容包,由于AndroidStudio在创建项目的时候会默认添加v7包的依赖,所以比较省事,如果还再用Eclise开发的小伙伴,就需要自己添加v7包的依赖。

三、Activity中,对toolbar进行相关设置

1.调用Toolbar相关的API
public class ToolBarActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_tool_bar);

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

        toolbar.setBackgroundColor(getResources().getColor(R.color.toolbar_bg));//设置Toolbar的背景颜色

        toolbar.setNavigationIcon(R.mipmap.ic_menu);//设置导航的图标
        toolbar.setLogo(R.mipmap.ic_launcher);//设置logo

        toolbar.setTitle("title");//设置标题
        toolbar.setSubtitle("subtitle");//设置子标题

        toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));//设置标题的字体颜色
        toolbar.setSubtitleTextColor(getResources().getColor(android.R.color.white));//设置子标题的字体颜色

        setSupportActionBar(toolbar);
    }

}

其中需要注意的是:

supportRequestWindowFeature(Window.FEATURE_NO_TITLE);

这句代码是不是觉得很眼熟,你以前肯定用过

requestWindowFeature(Window.FEATURE_NO_TITLE));

只是前面多了support,就和getFragmentManager()和getSupprotFragmentManager()差不多,由于ToolBarActivity继承AppCompatActivity,所以这里使用了supportRequestWindowFeature(Window.FEATURE_NO_TITLE),如果是继承Activity,则使用requestWindowFeature(Window.FEATURE_NO_TITLE)),这行代码是为了隐藏掉系统原先的导航栏,因为我们将使用Toolbar来代替。

隐藏导航栏的方法有两种:

  1. 在调用Activity的setContentView()方法之前,如果是继承AppCompatActivity,则调用supportRequestWindowFeature(Window.FEATURE_NO_TITLE),如果是继承Activity,则调用requestWindowFeature(Window.FEATURE_NO_TITLE))来隐藏导航栏。

  2. 为Activity设置一个NoActionBar的Theme,如Theme.AppCompat.Light.NoActionBar

以上代码运行后,效果如下:

是不是发现少了些什么,没错,少了右侧的搜索、添加菜单项。

此时,我们需要在Activity中,重写onCreateOptionsMenu()方法

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

getMenuInflater().inflate(R.menu.menu_tool_bar, menu);获取菜单填充器,将我们自定义的menu_tool_bar.xml文件填充。

2.设置菜单项的点击监听

要为菜单项设置点击监听,需要重写onOptionsItemSelected()方法,代码如下:

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    String tip = "";
    switch (id){
        case android.R.id.home://对应navigationIcon的点击
            tip = "菜单";
            break;
        case R.id.action_search:
            tip = "搜索";
            break;
        case R.id.action_add:
            tip = "添加";
            break;
        case R.id.action_setting:
            tip = "设置";
            break;
        case R.id.action_help:
           tip = "帮助";
            break;
    }
    Toast.makeText(this, tip, Toast.LENGTH_SHORT).show();
    return super.onOptionsItemSelected(item);
}

在该方法中,我们需要对id进行判断,在menu_tool_bar.xml文件中,对应的菜单项我们都有给予对应的id,如果想对navigationIcon做点击的处理,则当id为android.R.id.home的时候,做相关操作。

显示菜单项和设置点击监听的另一方法

上面提到如果想显示右侧的菜单项,则重写onCreateOptionsMenu()方法将对应的xml文件填充,需要设置点击监听,则重写onOptionsItemSelected()方法,根据id进行判断,做相关处理。还有另外一种方法实现上述的两个功能,不需要重写这两个方法,代码如下:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_tool_bar);

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

    toolbar.setBackgroundColor(getResources().getColor(R.color.toolbar_bg));//设置Toolbar的背景颜色

    toolbar.setNavigationIcon(R.mipmap.ic_menu);//设置导航的图标
    toolbar.setLogo(R.mipmap.ic_launcher);//设置logo

    toolbar.setTitle("title");//设置标题
    toolbar.setSubtitle("subtitle");//设置子标题

    toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));//设置标题的字体颜色
    toolbar.setSubtitleTextColor(getResources().getColor(android.R.color.white));//设置子标题的字体颜色

    //设置右上角的填充菜单
    toolbar.inflateMenu(R.menu.menu_tool_bar);
    //设置导航图标的点击事件
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(ToolBarActivity.this, "菜单", Toast.LENGTH_SHORT).show();
        }
    });
    //设置右侧菜单项的点击事件
    toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            int id = item.getItemId();
            String tip = "";
            switch (id) {
                case R.id.action_search:
                    tip = "搜索";
                    break;
                case R.id.action_add:
                    tip = "添加";
                    break;
                case R.id.action_setting:
                    tip = "设置";
                    break;
                case R.id.action_help:
                    tip = "帮助";
                    break;
            }
            Toast.makeText(ToolBarActivity.this, tip, Toast.LENGTH_SHORT).show();
            return false;
        }
    });;
}

当调用Toolbar的inflateMenu()方法加载menu布局时,无需再调用setSupportActionBar(),否则加载的是onCreateOptionsMenu()中的布局,点击时不会回调onOptionsItemSelected()方法,需要调用Toolbar的setOnMenuItemClickListener()方法,设置点击的监听,根据对应的id进行判断和处理,与onOptionsItemSelected()中处理不同的是,对应navigationIcon的点击事件,是在Toolbar的setNavigationOnClickListener()方法中进行处理。

Toolbar中添加自定义view

一开始我们提到Toolbar可以进行定制化修改,除了navigationIcon、logo、标题、子标题、菜单项外,还可以添加一些自定义控件(系统原有或自己写的控件),使用的方法很简单,布局文件中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="custom"
            android:textColor="@android:color/white"
            android:textSize="16sp"
            />

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

效果如下:

什么是DrawerLayout

DrawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说DrawerLayout是因为第三方控件如MenuDrawer等的出现之后,Google借鉴而出现的产物。DrawerLayout分为侧边菜单和主内容区两部分,侧边菜单可以根据手势展开与隐藏(DrawerLayout自身特性),主内容区的内容可以随着菜单的点击而变化(这需要使用者自己实现)。

结合DrawerLayout效果如下:

Toolbar + DrawerLayout 在日常开发中经常使用到,一般是那种侧滑菜单栏的App。

使用DrawerLayout的步骤

一、布局文件中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

        ... //此处省略toolbar
    
        <android.support.v4.widget.DrawerLayout
            android:id="@+id/drawlayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">


            <!--content-->
            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                >
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/content_text"
                    android:gravity="center"
                    android:layout_gravity="center"
                    android:textSize="16sp"
                    />
    
            </FrameLayout>
    
            <!--menu-->
            <FrameLayout
                android:layout_width="180dp"
                android:layout_height="match_parent"
                android:layout_gravity="left"
                android:background="@android:color/white"
                >
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="@android:color/black"
                    android:textSize="16sp"
                    android:text="@string/menu_text"
                    android:gravity="center"
                    android:layout_gravity="center"
                    />
    
    
            </FrameLayout>
    
    
        </android.support.v4.widget.DrawerLayout>
</LinearLayout>

使用DrawerLayout,需要添加v4包的依赖,AS创建项目的时候自带v4包的依赖,所以可以直接引用到。DrawerLayout中包括两个childView,一个为内容区域的根布局,另一个为侧边栏的根布局,如果是侧边栏的布局,需要指定其android:layout_gravity="left"或者android:layout_gravity="start"。需要注意的是,作为侧边栏的布局需要放置在内容区域下面,否则其子条目的点击事件将无法响应。

二、Activity中,将Toolbar和DrawerLayout结合

 private void initDrawerLayout() {
    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,mToolbar, R.string.open, R.string.close);

    mDrawerToggle.syncState();;///将ActionDrawerToggle与DrawerLayout的状态同步

    mDrawerLayout.setDrawerListener(mDrawerToggle);
}

使用DrawerLayout的小案例,效果如下

一、修改布局文件为:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

    ... //此处省略toolbar

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawlayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <!--content-->
        <FrameLayout
            android:id="@+id/fl_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            >

        </FrameLayout>

        <!--menu-->
        <ListView
            android:id="@+id/lv_list"
            android:layout_width="180dp"
            android:layout_height="match_parent"
            android:layout_gravity="left"
            android:background="@android:color/white"
            />

    </android.support.v4.widget.DrawerLayout>
</LinearLayout>

二、Activity中:

 @Override
protected void onCreate(Bundle savedInstanceState) {
     ...

    initView();
    initToolBar();
    initMenuTitles();
    initFragments();
    initDrawerLayout();
}

其中,为侧边栏的listView添加adapter,并设置条目的点击事件

    /**
     * 设置左侧菜单条目的标题
     */
     private void initMenuTitles() {
        mMenuTitles = getResources().getStringArray(R.array.menuTitles);
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mMenuTitles);
        mLvList.setAdapter(arrayAdapter);
        mLvList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                switchFragment(position);//切换fragment
                mDrawerLayout.closeDrawers();//收起DrawerLayout
            }
        });
    }

   /**
     * 切换fragment
     * @param index 下标
     */
    private void switchFragment(int index) {
        ContentFragment contentFragment = mFragments.get(index);
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.fl_content,contentFragment);
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        transaction.commit();
    }

好了,到此为止,ToolBar和DrawerLayout的使用,相信已经基本掌握了。需要源码的可以查看:

https://github.com/chaychan/MaterialDesignExercise

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

推荐阅读更多精彩内容

  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,658评论 22 664
  • 内容 抽屉菜单 ListView WebView SwitchButton 按钮 点赞按钮 进度条 TabLayo...
    小狼W阅读 1,608评论 0 10
  • Toolbar 是 Android 5.0 推出的一个 Material Design 风格的导航控件 ,用来取代...
    简奕凡阅读 1,513评论 0 4
  • #向有条不紊靠近# 孩子第二个30天目标: * 按时间起止点执行睡前清单 * 按时间起点执行睡前仪式,巩固早睡 *...
    emilybest1234阅读 217评论 0 0
  • 这两天电商的图书活动搞得轰轰烈烈的,有幸抽到一张二十一世纪出版社200-100的天猫券。该店铺有部分图书在执行五折...
    Cathy悦阅读 196评论 0 1