(收集转载总结)MD设计常用代码/尺寸/颜色/控件个人收集总结--控件部分

特别说明

当前博客平台账号已废弃,如果有使用细节问题请前往我新博客平台进行讨论交流。

个人博客平台 HuRuWo的技术小站

文章首发于个人博客HuRuWo的技术小站,如果本文非vip用户无法完全浏览或者图片无法打开,可前往个人博客文章地址查看文章并留言讨论。

个人博客文章地址(收集转载总结)MD设计常用代码/尺寸/颜色/控件个人收集总结--控件部分

更多技术文章访问本人博客HuRuWo的技术小站,包括 Electron从零开发 Android 逆向 app 微信数据抓取 抖音数据抓取 闲鱼数据抓取 小红书数据抓取 其他软件爬虫 等技术文章

前言

作为Android 开发者,不仅要学习功能的实现,还需要定制用户的界面。如何制作一款符合大家审美的app是个根令人头疼的问题。
不过好在google在15发布了MD设计规范,帮助程序员设计更好的app。

MD概述

说明:本文参考资料极客学院 Material Design 中文版
翻译不是很可靠,也不及时。最好还是去谷歌查看原文。

我们挑战自我,为用户创造了崭新的视觉设计语言。与此同时,新的设计语言除了遵循经典设计定则,还汲取了最新的科技,秉承了创新的设计理念。这就是原质化设计(Material Design)
。这份文档是动态更新的,将会随着我们对 Material Design 的探索而不断迭代、升级。

目标

我们希冀创造一种新的视觉设计语言,能够遵循优秀设计的经典定则,同时还伴有创新理念和新的科技。
我们希望创造一种独一无二的底层系统,在这个系统的基础之上,构建跨平台和超越设备尺寸的统一体验。遵循基本的移动设计定则,同时支持触摸、语音、鼠标、键盘等输入方式。

设计原则

实体感就是(通过设计方式来表达)隐喻
通过构建系统化的动效和空间合理化利用,并将两个理念合二为一,构成了实体隐喻。与众不同的触感是实体的基础,这一灵感来自我们对纸墨的研究,但是我们相信,随着科技的进步,应用前景将不可估量。
实体的表面和边缘提供基于真实效果的视觉体验,熟悉的触感让用户可以快速地理解和认知。实体的多样性可以让我们呈现出更多反映真实世界的设计效果,但同时又绝不会脱离客观的物理规律。
光效、表面质感、运动感这三点是解释物体运动规律、交互方式、空间关系的关键。真实的光效可以解释物体之间的交合关系、空间关系,以及单个物体的运动。

鲜明、形象、深思熟虑

新的视觉语言,在基本元素的处理上,借鉴了传统的印刷设计——排版、网格、空间、比例、配色、图像使用——这些基础的平面设计规范。在这些设计基础上下功夫,不但可以愉悦用户,而且能够构建出视觉层级、视觉意义以及视觉聚焦。精心选择色彩、图像、选择合乎比例的字体、留白,力求构建出鲜明、形象的用户界面,让用户沉浸其中。
Material Design 设计语言强调根据用户行为凸显核心功能,进而为用户提供操作指引。

有意义的动画效果

动画效果(简称动效)可以有效地暗示、指引用户。动效的设计要根据用户行为而定,能够改变整体设计的触感。
动效应当在独立的场景呈现。通过动效,让物体的变化以更连续、更平滑的方式呈现给用户,让用户能够充分知晓所发生的变化。
动效应该是有意义的、合理的,动效的目的是为了吸引用户的注意力,以及维持整个系统的连续性体验。动效反馈需细腻、清爽。转场动效需高效、明晰。

所有的关于MD设计的有关规范都能在该文档里找到,下面我们跟随文档,看下一些符合MD设计的应用是如何做到简约大方的。

热门开源MD风格设计App

  1. 简影讯,简约精彩影讯。仓库地址
    [图片上传失败...(image-47eebc-1606128193422)]
  2. 就看天气——是一款遵循Material Design风格的只看天气的APP。仓库地址
    [图片上传失败...(image-5cb39c-1606128193422)]

MD相关控件

参考文章:Android MD风格相关控件小结

CoordinatorLayout

CoordinatorLayout作为顶层布局,可以响应子布局的动作,调度协调子布局,形成优雅的动画效果。作为搭配主要有以下几种

CoordinatorLayout+AppBarLayout

CoordinatorLayout配合AppBarLayout 可以形成优雅的顶部导航条。配合ToolBar以及能让响应滑动事件的控件,可以形成根据滑动变化的顶部导航条。
能响应的滑动事件控件有:

  1. RecyclerView 控件
  2. NestedScrollView 里面的子控件

实例:一个常用的布局方式
CoordinatorLayout+AppBarLayout+ToolBar+TabLayout+ViewPager+RecyclerView

  1. CoordinatorLayout+AppBarLayout+ToolBar 制作响应的顶部导航
  2. TabLayout+ViewPager+RecyclerView 形成带Tab的ViewPager

布局文件:

主布局:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
<!---------------------------------隐藏toolbar----------------------------------->
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            app:title="MdView" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tablayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
<!---------------------------------ViewPage的滚动----------------------------------->
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:src="@android:drawable/ic_menu_share" />

</android.support.design.widget.CoordinatorLayout>

fragment布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.othershe.mdview.TypeFragment">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/type_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

配合CoordinatorLayout、AppBarLayout,我们实现了这样的效果,向上滚动列表时,Toolbar隐藏,TabLayout置顶,再向下滚动Toolbar则显示。
Toolbar之所以可以滚动隐藏\显示,是通过如下属性实现的:
app:layout_scrollFlags="scroll|enterAlways"

相关属性值解释如下

scroll:需要滚动出屏幕的view需要设置该flag, 没有设置则view将被固定在屏幕顶部。
enterAlways: 使用该flag,则向下的滚动会使view变为可见状态。

更多详情可参考文章玩转AppBarLayout,更酷炫的顶部栏

为Toolbar设置layout_scrollFlags属相只是第一步,还需要在CoordinatorLayout 中提供一个可滚动的View,我们使用ViewPager,并在里边嵌套RecyclerView。同时需要为ViewPager设置如下属性:app:layout_behavior="@string/appbar_scrolling_view_behavior"

其他有关代码:

 private void initContent() {
        mFragments = new ArrayList<>();
        mFragments.add(TypeFragment.newInstance("热点"));
        mFragments.add(TypeFragment.newInstance("军事"));
        mFragments.add(TypeFragment.newInstance("科技"));
        mFragments.add(TypeFragment.newInstance("娱乐"));

        mTitles = new ArrayList<>();
        mTitles.add("热点");
        mTitles.add("军事");
        mTitles.add("科技");
        mTitles.add("娱乐");

        TabPagerAdapter adapter = new TabPagerAdapter(getSupportFragmentManager());
        adapter.setArguments(mFragments, mTitles);
        mViewPager.setAdapter(adapter);

        //设置TabLayout可滚动,保证Tab数量过多时也可正常显示
        mTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
        //两个参数分别对应Tab未选中的文字颜色和选中的文字颜色
        mTabLayout.setTabTextColors(Color.WHITE, Color.RED);
        //绑定ViewPager
        mTabLayout.setupWithViewPager(mViewPager);
        //设置TabLayout的布局方式(GRAVITY_FILL、GRAVITY_CENTER)
        mTabLayout.setTabMode(TabLayout.MODE_FIXED);
        mTabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        //设置TabLayout的选择监听
        mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                mViewPager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            //重复点击时回调
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
                scrollToTop(mFragments.get(tab.getPosition()).getTypeList());
            }
        });
    }

    /**
     * 滚动到列表顶部
     *
     * @param recyclerView
     */
    private void scrollToTop(RecyclerView recyclerView) {
        StaggeredGridLayoutManager manager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager();
        int[] lastPositions = manager.findLastVisibleItemPositions(null);
        if (lastPositions[0] < 15) {
            recyclerView.smoothScrollToPosition(0);
        } else {
            recyclerView.scrollToPosition(0);
        }
    }

 public class TabPagerAdapter extends FragmentPagerAdapter {
        private List<TypeFragment> fragments;
        private List<String> titles;

        public TabPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        public void setArguments(List<TypeFragment> fragments, List<String> titles) {
            this.fragments = fragments;
            this.titles = titles;
        }

        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }

        @Override
        public int getCount() {
            return fragments.size();
        }

        //返回TabLayout对应Tab的标题
        @Override
        public CharSequence getPageTitle(int position) {
            return titles.get(position);
        }
    }

RecyclerView的Adapter

public class TypeListAdapter extends RecyclerView.Adapter<TypeListAdapter.ViewHolder> {

    private ArrayList<String> mDatas;
    private List<Integer> mHeights;
    private OnItemClickListener mListner;

    public TypeListAdapter(ArrayList<String> datas) {
        if (datas != null) {
            mDatas = datas;
        } else {
            mDatas = new ArrayList<>();
        }
        mHeights = new ArrayList<>();
        for (int i = 0; i < mDatas.size(); i++) {
            mHeights.add((int) (260 + Math.random() * 100));
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_type_layout, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        ViewGroup.LayoutParams params = holder.itemTv.getLayoutParams();
        params.height = mHeights.get(position);
        holder.itemTv.setLayoutParams(params);
        holder.itemTv.setText(mDatas.get(position));
        if (mListner != null) {
            holder.itemLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mListner.onItemClick(mDatas.get(position), position);
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.item_tv)
        TextView itemTv;
        @BindView(R.id.item_layout)
        View itemLayout;

        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        mListner = listener;
    }

    public interface OnItemClickListener {
        void onItemClick(String data, int position);
    }
}

效果:

CoordinatorLayout + AppBarLayout + CollapsingToolbarLayout

关于CollapsingToolbarLayout的说明

CollapsingToolbarLayout作用是提供了一个可以折叠的Toolbar,它继承至FrameLayout,给它设置layout_scrollFlags,它可以控制包含在CollapsingToolbarLayout中的控件(如:ImageView、Toolbar)在响应layout_behavior事件时作出相应的scrollFlags滚动事件(移除屏幕或固定在屏幕顶端)。

所以我们尝试加一个ImageView在里面试试,同时添加
app:layout_scrollFlags="scroll|exitUntilCollapsed"

再加一个响应滑动的控件,除了RecyclerView还有一个NestedScrollView控件同理加上app:layout_behavior="@string/appbar_scrolling_view_behavior"

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:id="@+id/detail_content"
    tools:context="com.othershe.mdview.DetailActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
<!---------------------------折叠-------------------------->
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/detail_img"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="fitXY"
     <!---------------------------折叠-------------------------->
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
       <!---------------------------折叠-------------------------->
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <WebView
            android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </android.support.v4.widget.NestedScrollView>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@android:drawable/ic_menu_share"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|end" />

</android.support.design.widget.CoordinatorLayout>

可以看到:
CollapsingToolbarLayout添加了两个子控件,由于CollapsingToolbarLayout本质是一个Fragmentlayout,所以层叠显示。同时设置ToolBar背景透明。

关于返回箭头:

//使mToolbar取代原来的ActionBar
        setSupportActionBar(mToolbar);
        //设置mToolbar左上角显示返回图标
        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }
        //设置返回图标的点击事件
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

其他代码

 //设置还没收缩时状态下字体颜色
        mToolbarLayout.setExpandedTitleColor(Color.RED);
        //设置收缩后Toolbar上字体的颜色
        mToolbarLayout.setCollapsedTitleTextColor(Color.WHITE);
        //设置image背景
        mDetailImg.setBackgroundResource(R.mipmap.bg);

        mWebView.loadUrl("http://www.jianshu.com/");
        mWebView.setWebChromeClient(new WebChromeClient() {

            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
                //必须把title设置到CollapsingToolbarLayout上,设置到Toolbar上则不会显示
                mToolbarLayout.setTitle(title);
            }
        });

结合CollapsingToolbarLayout,我们向上滑动时ImageView隐藏、Toolbar显示,向下滑动则反之,类似折叠展开的效果。

在CollapsingToolbarLayout中通过app:contentScrim="?attr/colorPrimary"属相设置Toolbar折叠到顶部的背景,同时设置了app:layout_scrollFlags="scroll|exitUntilCollapsed"属相,其中scroll的=含义已经解释过了,exitUntilCollapsed的含义如下:

exitUntilCollapsed: 滚动退出屏幕,最后折叠在顶端

同时AppBarLayout的高度需要时第一个固定值,这样CollapsingToolbarLayout就有了折叠的效果。

折叠后Toolbar可以固定在顶部是因为使用了app:layout_collapseMode="pin"属性,属性值除了pin还有一个parallax:

pin:固定模式,在折叠的时候最后固定在顶端
parallax:视差模式,在折叠时会有个视差折叠的效果

同时在ImageView中使用了app:layout_collapseMode="parallax"属性,来产生视差渐变的效果,使用app:layout_collapseParallaxMultiplier="0.7"可以控制视差的变化,属性值的范围是[0.0, 1.0],值越大视察越大。

最后还需要在NestedScrollView中设置app:layout_behavior="@string/appbar_scrolling_view_behavior属性。

CoordinatorLayout+FloatingActionButton

这个很简单,只要加入了FloatingActionButton即可响应

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        ........................................
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:src="@android:drawable/ic_menu_share" />

</android.support.design.widget.CoordinatorLayout>

代码

mFab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(mCoordinatorLayout, "点我分享哦!", Snackbar.LENGTH_SHORT).show();
            }
        });

在Snackbar展示的时候FloatingActionButton上移,隐藏时下移。如果FloatingActionButton的父View是RelativeLayout或其它Container则FloatingActionButton不会上移而导致被Snackbar覆盖。

要做到我们上滑时FloatingActionButton会折叠消失,其实只需要如下两个属性就可以

app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|end"

第一个属性使FloatingActionButton显示在AppBarLayout的区域,
第二个属性确定显示的具体位置。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:id="@+id/detail_content"
    tools:context="com.othershe.mdview.DetailActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

      .............................
    </android.support.design.widget.AppBarLayout>

    .........................
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@android:drawable/ic_menu_share"
<!--------------------------在app_bar中------------------->
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|end" />

</android.support.design.widget.CoordinatorLayout>

用来替换yuanlaide

Toolbar

ToolBar的出现是为了替换之前的ActionBar的各种不灵活使用方式,相反,ToolBar的使用变得非常灵活,因为它可以让我们自由往里面添加子控件。我们可以单独的使用也可以代替原来的ActionBar。

替换ActionBar

  1. 使用Toolbar首先要隐藏原有的ActionBar,我们可以增加一个主题
<style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

也可以扩展原有的主题,

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

colorPrimary:对应ActionBar的颜色。
colorPrimaryDark:对应状态栏的颜色
colorAccent:对应EditText编辑时、FloatingActionButton背景等颜色。

配置文件修改:Android:theme=”@style/AppTheme”

  1. 在布局文件中的用法可以参考上边的代码,之后在java代码中得到Toolbar,通过setSupportActionBar(mToolbar);使Toolbar取代原本的ActionBar。

相关属性

<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary">
        <!--添加Toolbar的子控件-->
        <Button
            android:id="@+id/btn_diy"
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:background="#80ffffff"
            android:text="自定义按钮"
            android:textColor="#000000"
            android:textSize="11sp" />

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="首页"
            android:textColor="@android:color/black"
            android:textSize="20sp" />
    </android.support.v7.widget.Toolbar>

?attr/actionBarSize:表示根据屏幕的分辨率采用系统默认的高度

关于图标以及其他设置:参考图片对应方法


 mToolbar = (Toolbar) findViewById(R.id.toolbar);
        // App Logo
//        mToolbar.setLogo(R.drawable.app_icon);
        // 主标题,默认为app_label的名字
        mToolbar.setTitle("Title");
        mToolbar.setTitleTextColor(Color.YELLOW);
        // 副标题
        mToolbar.setSubtitle("Sub title");
        mToolbar.setSubtitleTextColor(Color.parseColor("#80ff0000"));
        //侧边栏的按钮
        mToolbar.setNavigationIcon(R.drawable.back);
        //取代原本的actionbar
        setSupportActionBar(mToolbar);
        //设置NavigationIcon的点击事件,需要放在setSupportActionBar之后设置才会生效,
        //因为setSupportActionBar里面也会setNavigationOnClickListener
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mToast.setText("click NavigationIcon");
                mToast.show();
            }
        });
        //设置toolBar上的MenuItem点击事件
        mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.action_edit:
                        mToast.setText("click edit");
                        break;
                    case R.id.action_share:
                        mToast.setText("click share");
                        break;
                    case R.id.action_overflow:
                        //弹出自定义overflow
                        popUpMyOverflow();
                        return true;
                }
                mToast.show();
                return true;
            }
        });
        //ToolBar里面还可以包含子控件
        mToolbar.findViewById(R.id.btn_diy).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mToast.setText("点击自定义按钮");
                mToast.show();
            }
        });
        mToolbar.findViewById(R.id.tv_title).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mToast.setText("点击自定义标题");
                mToast.show();
            }
        });

设置menu,以及item点击事件

//如果有Menu,创建完后,系统会自动添加到ToolBar上
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

 @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id) {
            case R.id.menu_share:
                break;
            case R.id.menu_search:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

NavigationView

NavigationView的就是抽屉,是隐藏在界面外的一个布局。
在MD设计规范里,主要的东西应该是显眼的,用户直达的。所以NavigationView只能放一些次要的东西。比如说明、设置等等

布局文件

其实NavigationView就是用来实现我们常见的侧滑菜单的效果的。
在布局文件中的代码:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <include
        layout="@layout/content_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:menu="@menu/menu_drawer"
        app:headerLayout="@layout/nav_head_main" />

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

以DrawerLayout作为根布局,content_main作为主界面布局,最后是NavigationView,
通过android:layout_gravity="start"设置为左侧滑菜单,
同理android:layout_gravity="end"代表右侧滑菜单。
其中

app:menu="@menu/menu_drawer"
app:headerLayout="@layout/nav_head_main"

两个属性分别代表NavigationView的顶部header布局以及下边的menu item布局,具体可以参考源代码。
nav_head_main.xml

<?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="180dp"
    android:background="#309393"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/nav_head_icon"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginLeft="20dp"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/nav_head_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:textSize="18sp" />

</LinearLayout>

menu_drawer.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_item1"
            android:icon="@android:drawable/ic_menu_compass"
            android:title="我的圈子" />
        <item
            android:id="@+id/nav_item2"
            android:icon="@android:drawable/ic_menu_add"
            android:title="我的收藏" />
    </group>

    <item android:title="其它">
        <menu>
            <item
                android:id="@+id/nav_set"
                android:icon="@android:drawable/ic_menu_crop"
                android:title="设置" />
            <item
                android:id="@+id/menu_share"
                android:icon="@android:drawable/ic_menu_share"
                android:title="分享" />
            <item
                android:id="@+id/nav_about"
                android:icon="@android:drawable/ic_menu_help"
                android:title="关于" />
        </menu>
    </item>
</menu>

代码

准备好了布局文件,接下来就是初始化工作:

private void initNavigationView() {
        //初始化NavigationView顶部head的icon和name
        ImageView icon = (ImageView) mNavView.getHeaderView(0).findViewById(R.id.nav_head_icon);
        icon.setImageResource(R.mipmap.ic_launcher);
        TextView name = (TextView) mNavView.getHeaderView(0).findViewById(R.id.nav_head_name);
        name.setText("VipOthershe");
        //设置NavigationView对应menu item的点击事情
        mNavView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.nav_item1:
                        break;
                    case R.id.nav_item2:
                        break;
                    case R.id.nav_set:
                        break;
                    case R.id.menu_share:
                        break;
                    case R.id.nav_about:
                        break;
                }
                //隐藏NavigationView
                mDrawerLayout.closeDrawer(GravityCompat.START);
                return true;
            }
        });
    }

很简单,就是初始化NavigationView的顶部header和Menu Item。

接下来看一下如何将右滑菜单和Toolbar结合使用:

ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, mDrawerLayout, mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        mDrawerLayout.addDrawerListener(toggle);
        //设置左上角显示三道横线
        toggle.syncState();

通过设置将两者绑定在一起,同时Toolbar左上角显示三道横线,左上角可打开左滑菜单。

还可以采用另外一种方式:

 //设置Toolbar左上角图标
        mToolbar.setNavigationIcon(R.mipmap.ic_launcher);
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mDrawerLayout.openDrawer(GravityCompat.START);
            }
        });

先设置Toolbar左上角图标,并绑定事件,通过mDrawerLayout.openDrawer(GravityCompat.START);打开左滑菜单。

以上两个方法,分别对应打开和关闭左滑菜单:

mDrawerLayout.openDrawer(GravityCompat.START);
mDrawerLayout.closeDrawer(GravityCompat.START);

如果使用右滑菜单则将GravityCompat.START改成GravityCompat.END,即可实现右滑菜单的开关。

效果图

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

推荐阅读更多精彩内容