android系统控件support designMaterial Design

Android Design Support Library系列

2017-05-12  本文已影响647人  滴滴滴9527

一、 DrawerLayout

DrawerLayout官网教程
DrawerLayout官网API
在很多应用中都会有抽屉式导航栏,鉴于此,谷歌就提供了DrawerLayout来实现这个功能.


DrawerLayout在v4包中,使用时需要导入v4包,使用eclipse创建项目会自动导入v4包,使用studio创建项目时会自动添加v7依赖,v7是兼容v4的,所以直接用就是了......

1、 DrawerLayout的简单使用

DrawerLayout的使用非常简单,只要遵循几个规则就行了
布局文件:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/tv_main"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="主页面" />
    </RelativeLayout>

    <ListView
        android:id="@+id/list_view"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@android:color/holo_blue_dark"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:scrollbars="none" />

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

直接使用DrawerLayout作为根标签,然后DrawerLayout根据android:layout_gravity属性判断哪个是侧滑面板,使用start/end或者left/right来表明是抽屉式导航栏是左边的还是右边的,没有android:layout_gravity属性的就是主页面视图了.

ok,简单的侧滑效果完成了,就是这么简单,来看一下效果图:


是不是很简单,官网介绍了使用DrawerLayout的几条规范:
1、DrawerLayout最好声明为根标签
2、在DrawerLayout中,主页面视图(上面的 TextView那一部分,当然,这个内容是你自己决定的,不一定要是TextView)必须是第一个子视图
3、主页面视图设置为匹配父视图的宽度和高度, 因为在抽屉式导航栏处于隐藏状态时, 它代表整个 UI
4、抽屉式导航栏视图 必须使用 android:layout_gravity属性指定
如果要支持“从右到左”(RTL) 语言,请使用 "start"(而非"left")指定该值(这样当布局为 RTL 时,抽屉式导航栏会显示在右侧)。

PS:RTL就是从右到左(Right To Left)的布局,我们在手机上/设置/开发者选项中有一个强制使用从右到左的布局方向,可以打开试一试效果.
虽然我们国内app一般都是从左到右,但我们还是听谷歌的建议比较好,使用start/end而非left/right.

5、抽屉式导航栏视图以 dp 为单位指定其宽度, 且高度与父视图相匹配。抽屉式导航栏的宽度不应超过 320dp,从而用户始终可以看到部分主内容。

2、 抽屉的数据填充

抽屉其实只是一个普通的View,这里我放的是ListView,看起来就像菜单,当然,你完全可以只放一个ImageView、TextView等等。这和Activity的菜单不一样,Activity的菜单只需要在资源文件中定义好,就能按照固定的形式显示出来。而DrawerLayout的侧边菜单显示成什么样完全是取决于你自己,同样点击菜单之后的逻辑也完全由你自己去写。

接下来给菜单填充数据
布局文件

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/tv_main"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="主页面" />
        <Button
            android:id="@+id/bt_open"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="打开" />

    </RelativeLayout>

    <ListView
        android:id="@+id/list_view"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@android:color/holo_blue_dark"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:scrollbars="none" />

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

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private List<String> mDatas;
    private DrawerLayout mDrawerLayout;
    private ListView mListView;
    private TextView tvMain;
    private Button btOpen;


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

        initData();
        initView();

        mListView.setAdapter(new ArrayAdapter<>(MainActivity.this,android.R.layout.simple_list_item_1,mDatas));

        /**
         * 点击菜单条目更改主界面TextView内容,同时关闭菜单
         *      关闭菜单使用DrawerLayout.closeDrawer()方法,传入要关闭的菜单View或者菜单的方向都可以
         */
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                tvMain.setText(mDatas.get(position));
                mDrawerLayout.closeDrawer(mListView);
//              mDrawerLayout.closeDrawer(GravityCompat.START);
            }
        });

        /**
         *  打开菜单使用DrawerLayout.openDrawer()方法,传入要关闭的菜单View或者菜单的方向都可以
         */
        btOpen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mDrawerLayout.openDrawer(GravityCompat.START);
//              mDrawerLayout.openDrawer(mListView);
            }
        });
    }

    private void initView() {
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mListView = (ListView) findViewById(R.id.list_view);
        tvMain = (TextView) findViewById(R.id.tv_main);
        btOpen = (Button) findViewById(R.id.bt_open);
    }

    private void initData() {
        mDatas = new ArrayList<>();
        for (int i = 'A'; i < 'Z'; i++) {
            mDatas.add("" + (char) i);
        }
    }
}

效果图


实际开发中这里的主页面视图一般用FrameLayout代替,点击菜单条目,动态为FrameLayout添加内容.
ok,简单的介绍了DrawerLayout的使用,接下来来看一下我们今天的主角

二、NavigationView

NavigationView官网教程

1、NavigationView是什么

NavigationView就是菜单View,也就是上面我们使用的ListView那一部分。
那么,有了DrawerLayout之后为什么还会出现一个NavigationView,看下面这张图:



这种效果的菜单用ListView或者RecyclerView也能实现,不过总要花点时间吧,但是用NavigationView之后简直分分钟搞定.

2、NavigationView的使用

(1)简单使用

<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">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/tv_main"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="主页面" />
    </RelativeLayout>

    
    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/header"
        app:menu="@menu/main">
    </android.support.design.widget.NavigationView>


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

NavigationView就是菜单面板,其中最重要的两条属性就是:

1、这就是菜单面板的头布局,也就是刚才头像,昵称那一栏,引用了一个布局文件
 app:headerLayout="@layout/header"

header.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="150dp"
    android:background="@color/colorPrimaryDark"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:layout_width="144dp"
        android:layout_height="90dp"
        android:layout_marginTop="10dp"
        android:background="@mipmap/icon" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="随风飘扬的smile"
        android:textColor="@android:color/white"
        android:textSize="15sp" />
</LinearLayout>
2、这就是菜单面板的内容部分,也就是会员特权、XX钱包...那一部分,定义在res/menu/main.xml中
app:menu="@menu/main"

main.xml

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

        <item
            android:id="@+id/item_1"
            android:icon="@mipmap/a"
            android:title="会员特权" />

        <item
            android:id="@+id/item_2"
            android:icon="@mipmap/b"
            android:title="XX钱包" />

        <item
            android:id="@+id/item_3"
            android:icon="@mipmap/c"
            android:title="个性装扮" />
        <item
            android:id="@+id/item_4"
            android:icon="@mipmap/d"
            android:title="我的收藏" />
        <item
            android:id="@+id/item_5"
            android:icon="@mipmap/e"
            android:title="我的相册" />

        <item
            android:id="@+id/item_6"
            android:icon="@mipmap/f"
            android:title="设置" />
</menu>

header和item部分内容都是根据实际需要来设置的.
(2)效果图:


效果有点不一样,没有了分隔线,而且图片都是灰灰的。

(3)添加分隔线:

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

        <group android:id="@+id/group1">
                <item
                    android:id="@+id/item_1"
                    android:icon="@mipmap/a"
                    android:title="会员特权" />
        </group>

        <group android:id="@+id/group2">
                <item
                    android:id="@+id/item_2"
                    android:icon="@mipmap/b"
                    android:title="XX钱包" />
        </group>

        <group android:id="@+id/group3">
                <item
                    android:id="@+id/item_3"
                    android:icon="@mipmap/c"
                    android:title="个性装扮" />
        </group>
        <group android:id="@+id/group4">
                <item
                    android:id="@+id/item_4"
                    android:icon="@mipmap/d"
                    android:title="我的收藏" />
        </group>
        <group android:id="@+id/group5">
                <item
                    android:id="@+id/item_5"
                    android:icon="@mipmap/e"
                    android:title="我的相册" />
        </group>

        <group android:id="@+id/group6">
                <item
                    android:id="@+id/item_6"
                    android:icon="@mipmap/f"
                    android:title="设置" />
        </group>
</menu>

在菜单条目文件中给item分组,就可以添加分隔线了。
再来看效果图:


ok!
(4)解决图片变灰问题:
方式1:你可以为NavigationView设置下面这条属性,不过那样item图片只能是统一的颜色
app:itemIconTint=""

方式2:Activity中代码设置,这样能让图片恢复原样了

mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
mNavigationView.setItemIconTintList(null);

ok,现在效果图和刚开始那张图完全一样了。

(5)item继续添加分组:

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

        <group android:id="@+id/group1">
                <item
                    android:id="@+id/item_1"
                    android:icon="@mipmap/a"
                    android:title="会员特权" />
        </group>

        <group android:id="@+id/group2">
                <item
                    android:id="@+id/item_2"
                    android:icon="@mipmap/b"
                    android:title="XX钱包" />
        </group>

        <group android:id="@+id/group3">
                <item
                    android:id="@+id/item_3"
                    android:icon="@mipmap/c"
                    android:title="个性装扮" />
        </group>
        <group android:id="@+id/group4">
                <item
                    android:id="@+id/item_4"
                    android:icon="@mipmap/d"
                    android:title="我的收藏" />
        </group>
        <group android:id="@+id/group5">
                <item
                    android:id="@+id/item_5"
                    android:icon="@mipmap/e"
                    android:title="我的相册" />
        </group>

        <group android:id="@+id/group6">
                <item
                    android:id="@+id/item_6"
                    android:icon="@mipmap/f"
                    android:title="设置" />
        </group>

        <group android:id="@+id/group7">
                <item
                    android:id="@+id/item_7"
                    android:icon="@mipmap/f"
                    android:title="其它" >
                        <menu>
                                <item
                                    android:id="@+id/item_8"
                                    android:icon="@mipmap/f"
                                    android:title="分享" />
                                <item
                                    android:id="@+id/item_9"
                                    android:icon="@mipmap/f"
                                    android:title="隐私" />

                        </menu>

                </item>
        </group>
</menu>

效果图:



当item过多会出现滚动条,如果要隐藏滚动条,给NavigationView设置android:scrollbars="none"是不管用的,因为这个滚动条不是NavigationView的,而是菜单的·.
可以在Activity中找到菜单View,然后取消滚动条

NavigationMenuView menuView  = (NavigationMenuView) mNavigationView.getChildAt(0);
menuView.setVerticalScrollBarEnabled(false);
3、NavigationView其它属性
给菜单item部分添加背景
 app:itemBackground=" "
给菜单item文字设置颜色
app:itemTextColor=" "

更多文字特效可以通过下面这条属性设置:
app:itemTextAppearance=" "
4、菜单item的一些属性
设定一组菜单项可以选中几个item,none、single、all三个值
  <group android:id="@+id/group1" android:checkableBehavior="single"> 
菜单项 item 是否被选中,如果要默认选中一个菜单 item 则设为true
<item   android:checked="true" />
5、NavigationView点击事件

(1)头部点击事件

        headerView = mNavigationView.getHeaderView(0);

        headerView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"headerView",Toast.LENGTH_SHORT).show();
            }
        });

找到headerView ,然后设置点击事件即可
(2)头部控件点击事件
通过headerView.findViewById()找到要点击的控件,然后设置点击事件即可

        ivIcon = (ImageView) headerView.findViewById(R.id.icon);
        tvName = (TextView) headerView.findViewById(R.id.name);

        ivIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"icon",Toast.LENGTH_SHORT).show();
            }
        });

        tvName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"name",Toast.LENGTH_SHORT).show();
            }
        });

(3)item点击事件

通过NavigationView.setNavigationItemSelectedListener()设置监听即可
        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()){
                    case R.id.item_1:
                        //do something
                        break;
                    case R.id.item_2:
                        //do something
                        break;
                   //......
                }
                return false;
            }
        });

(4)隐藏菜单某部分item
有时候可能会有些奇葩的需求,要求我们隐藏一些菜单item,满足一定条件才会显示出来.

MenuItem item = mNavigationView.getMenu().findItem(R.id.item_1);//找到要隐藏的item
item.setVisible(false);//false即隐藏,true即显示

三、 完整代码

Activity布局文件:

<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">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/tv_main"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="主页面" />
    </RelativeLayout>

    
    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="left"
        app:itemTextColor="@color/colorPrimaryDark"
        app:headerLayout="@layout/header"
        app:menu="@menu/main">

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

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

header布局文件:

<?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="150dp"
    android:background="@color/colorPrimaryDark"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="144dp"
        android:layout_height="90dp"
        android:layout_marginTop="10dp"
        android:background="@mipmap/icon" />

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="随风飘扬的smile"
        android:textColor="@android:color/white"
        android:textSize="15sp" />
</LinearLayout>

菜单文件

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

    <group android:id="@+id/group1">
        <item
            android:id="@+id/item_1"
            android:icon="@mipmap/a"
            android:title="会员特权" />
    </group>

    <group android:id="@+id/group2">
        <item
            android:id="@+id/item_2"
            android:icon="@mipmap/b"
            android:title="XX钱包" />
    </group>

    <group android:id="@+id/group3">
        <item
            android:id="@+id/item_3"
            android:icon="@mipmap/c"
            android:title="个性装扮" />
    </group>
    <group android:id="@+id/group4">
        <item
            android:id="@+id/item_4"
            android:icon="@mipmap/d"
            android:title="我的收藏" />
    </group>
    <group android:id="@+id/group5">
        <item
            android:id="@+id/item_5"
            android:icon="@mipmap/e"
            android:title="我的相册" />
    </group>

    <group android:id="@+id/group6">
        <item
            android:id="@+id/item_6"
            android:icon="@mipmap/f"
            android:title="设置" />
    </group>

    <group android:id="@+id/group7">
        <item
            android:id="@+id/item_7"
            android:icon="@mipmap/f"
            android:title="其它">
            <menu>
                <item
                    android:id="@+id/item_8"
                    android:icon="@mipmap/f"
                    android:title="分享" />
                <item
                    android:id="@+id/item_9"
                    android:icon="@mipmap/f"
                    android:title="隐私" />
            </menu>
        </item>
    </group>
</menu>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private DrawerLayout mDrawerLayout;
    private TextView tvMain;
    private NavigationView mNavigationView;
    private View headerView;
    private ImageView ivIcon;
    private TextView tvName;

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

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        tvMain = (TextView) findViewById(R.id.tv_main);
        mNavigationView = (NavigationView) findViewById(R.id.navigation_view);

        mNavigationView.setItemIconTintList(null);//让菜单item图片正常


//          隐藏菜单item
//        MenuItem item = mNavigationView.getMenu().findItem(R.id.item_1);
//        item.setVisible(false);

        /**
         * 隐藏滚动条
         */
        NavigationMenuView menuView  = (NavigationMenuView) mNavigationView.getChildAt(0);
        menuView.setVerticalScrollBarEnabled(false);


        /**
         * header点击事件
         */
        headerView = mNavigationView.getHeaderView(0);
        headerView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"headerView",Toast.LENGTH_SHORT).show();
            }
        });

        /**
         * headerView中组件点击事件
         */
        ivIcon = (ImageView) headerView.findViewById(R.id.icon);
        tvName = (TextView) headerView.findViewById(R.id.name);

        ivIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"icon",Toast.LENGTH_SHORT).show();
            }
        });

        tvName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"name",Toast.LENGTH_SHORT).show();
            }
        });


        /**
         * 菜单item点击事件
         */
        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.item_1:
                        //do something
                        break;
                    case R.id.item_2:
                        //do something
                        break;
                    //......
                }
                return false;
            }
        });
    }
}

效果图

上一篇下一篇

猜你喜欢

热点阅读