在(一)https://blog.csdn.net/qq_36551426/article/details/80427352中讲了一下DrawerLayout的简单概念,但是这并不足以让我们去做一个完整的QQ侧滑菜单。首先如果只是简单的在侧面菜单里出现一些list还好,可以通过listview配合adapter的方式对菜单初始化。但是如果要完成再乱七八糟点的呢?可能我们需要一些新的View了。
下面我们来看一下NavigationView导航菜单,NavigationView继承自FrameLayout。一般用于应用的导航菜单,菜单的内容来自于menu文件。NavigationView通常放置在DrawerLayout内部。
可能在这里我们还不是特别清楚这个View的作用是什么,大家新建工程的时候注意没有,其实空工程下面是有很多其他类型的模板工程的,其中一个就有DrawerLayout的模板。我们打开看看里面结构是什么样的。
可以看到大体的文件结构。
具体的效果,左边这个就是NavigationView了。这里分了两个结构,一个是上面的head,下面是一个menu。我们看一下具体的activity_main.XML:
<?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" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> <include layout="@layout/app_bar_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:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" /> </android.support.v4.widget.DrawerLayout>
这里很简单,只有一个app_bar_main和一个NavigationView。外面是一个DrawerLayout。
再看一下app_bar_main:
<?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" tools:context=".MainActivity"> <android.support.design.widget.AppBarLayout 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" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" app:srcCompat="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>
一个toolbar,一个content_main,一个FloatingActionButton(悬浮按钮,在这里可以忽略)。
content_main里面:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context=".MainActivity" tools:showIn="@layout/app_bar_main"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
只有一个TextView。到这里,就可以看清楚整个布局结构了。主界面一个titlebar的xml,下面一个navigationview。然后titlebar里负责主界面的title之类的东西。而navigationview里的上下结构怎么放呢?再来看下面的headerlayout和menu:
headerlayout的效果,这里不贴代码了,看一看结构,一个ImageView,两个TextView,垂直结构:
下面是menu的代码,menu在之前的文章已经讲过了https://blog.csdn.net/qq_36551426/article/details/80398403不了解的同学可以再看一下:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:showIn="navigation_view"> <group android:checkableBehavior="single"> <item android:id="@+id/nav_camera" android:icon="@drawable/ic_menu_camera" android:title="Import" /> <item android:id="@+id/nav_gallery" android:icon="@drawable/ic_menu_gallery" android:title="Gallery" /> <item android:id="@+id/nav_slideshow" android:icon="@drawable/ic_menu_slideshow" android:title="Slideshow" /> <item android:id="@+id/nav_manage" android:icon="@drawable/ic_menu_manage" android:title="Tools" /> </group> <item android:title="Communicate"> <menu> <item android:id="@+id/nav_share" android:icon="@drawable/ic_menu_share" android:title="Share" /> <item android:id="@+id/nav_send" android:icon="@drawable/ic_menu_send" android:title="Send" /> </menu> </item> </menu>
说白了就是一堆menu,内嵌一堆item。item设置了属性,id、icon、title。
OK,总结一下,要做这个效果就是在DrawerLayout里面加NavigationView,然后NavigationView里放两个布局,一个head,一个menu。这样侧滑菜单栏就出现了,而主菜单又是另外一个部分,我们目前大可以不管。
//---------------------------------------下面我们创建空工程来做自己的侧滑效果-----------------------------------------
首先分析一下,一个侧滑菜单,用到DrawerLayout,然后上面有我们自己DIY的title,下面先放空白,侧滑菜单放在NavigationView里。NavigationView很自然的帮我们分为了上下(head,menu)两个部分,上面用来放我们QQ头像,签名等信息。下面是QQ的一些菜单选项如QQ会员,相册。
OK,在activity_main.xml里放好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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/my_drawer_layout" tools:context=".MainActivity"> <android.support.design.widget.NavigationView android:id="@+id/Nav_view" app:menu="@menu/nav_menu" android:layout_gravity="left" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_head" android:layout_width="340dp" android:layout_height="match_parent"/> </android.support.v4.widget.DrawerLayout>
接下来,我们在res文件夹内建一个menu文件夹,再建一个nav_menu.xml在里面,装上item:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/nav_menu_vip" android:icon="@drawable/ic_menu_camera" android:title="我的QQ会员" /> <item android:id="@+id/nav_menu_wallet" android:icon="@drawable/ic_menu_camera" android:title="QQ钱包" /> <item android:id="@+id/nav_menu_zhuangban" android:icon="@drawable/ic_menu_camera" android:title="个性装扮" /> <item android:id="@+id/nav_menu_shouchang" android:icon="@drawable/ic_menu_camera" android:title="我的收藏" /> <item android:id="@+id/nav_menu_album" android:icon="@drawable/ic_menu_camera" android:title="我的相册" /> <item android:id="@+id/nav_menu_file" android:icon="@drawable/ic_menu_camera" android:title="我的文件" /> <item android:id="@+id/nav_menu_liuliang" android:icon="@drawable/ic_menu_camera" android:title="免流量特权" /> </menu>
看到这个图,别慌!
然后是headlayout,在layout里建一个nav_head.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:id="@+id/nav_head_view" android:background="@drawable/side_nav_bar" android:orientation="vertical" android:layout_height="180dp"> <ImageView android:id="@+id/head_im" android:layout_width="90dp" android:layout_height="90dp" android:layout_marginLeft="12dp" android:layout_marginTop="36dp" android:src="@drawable/head" /> <TextView android:text="刘敏敏我爱你刘敏敏我爱你刘敏敏我爱你" android:textSize="18sp" android:layout_marginLeft="12dp" android:layout_marginTop="5dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
ImageView跟TextView随便放,按自己的效果来。别忘了LinearLayout放背景图。
在这里已经可以有一个侧滑菜单栏的效果了,不过我们还可以再进一步,自定义一个Title,里面放一个Button跟一个TextView。Button响应侧滑菜单。这算是模拟QQ主界面点击头像打开侧滑菜单的效果。
title的代码跟模板的一模一样:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:theme="@style/AppTheme" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="wrap_content" android:layout_height="wrap_content"> <Button android:id="@+id/toolbar_btn" android:background="@drawable/ic_menu_manage" android:layout_width="50dp" android:layout_height="50dp" /> <TextView android:textSize="24sp" android:layout_marginLeft="60dp" android:text="@string/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> </android.support.constraint.ConstraintLayout>
然后把title放进main.xml里就可以了。
OK,在这里也差不多了,接下来是通过代码响应一下事件。1、点击button打开关闭侧滑菜单栏。2、点击menu内的item响应事件,并关闭菜单。
我们继承Navigation.OnNavigationItemSelectedListener,和View.OnClickListener。顾名思义,就是响应item点击事件和button点击事件。
package comr.example.administrator.mydrawertest3; import android.app.Activity; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.Gravity; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity implements NavigationView.OnNavigationItemSelectedListener, View.OnClickListener { private Button button; private NavigationView navigationView; private DrawerLayout drawerLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); drawerLayout = (DrawerLayout)findViewById(R.id.my_drawer_layout); button = (Button)findViewById(R.id.toolbar_btn); button.setOnClickListener(this); navigationView = (NavigationView) findViewById(R.id.Nav_view); navigationView.setNavigationItemSelectedListener(this); } /** * 对navigationview里的item监听 * @param item * @return */ @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { DrawerLayout drawer = (DrawerLayout) findViewById(R.id.my_drawer_layout);//新变量 //对于这类点击响应事件,都是对参数getId,因为在底层这些Id都是一串数值,通过数值比较来确定目标 switch (item.getItemId()){ //每点击一次菜单中的item就showtoast一次然后将drawerlayout关闭 case R.id.nav_menu_album: showToast("相册"); drawer.closeDrawer(Gravity.LEFT); break; case R.id.nav_menu_file: showToast("文件"); drawer.closeDrawer(Gravity.LEFT); break; case R.id.nav_menu_liuliang: showToast("流量"); drawer.closeDrawer(Gravity.LEFT); break; case R.id.nav_menu_shouchang: showToast("收藏"); drawer.closeDrawer(Gravity.LEFT); break; case R.id.nav_menu_vip: showToast("VIP"); drawer.closeDrawer(Gravity.LEFT); break; case R.id.nav_menu_wallet: showToast("钱包"); drawer.closeDrawer(Gravity.LEFT); break; case R.id.nav_menu_zhuangban: showToast("装扮"); drawer.closeDrawer(Gravity.LEFT); break; default: break; } return true; } private void showToast(String s) { Toast.makeText(this,s,Toast.LENGTH_SHORT).show(); } /** * implement clickListener接口,对事件做点击监听,其实也可以对navigationview里的item做监听 * 但是可以通过implement NavigationView的OnNavigationItemSelectedListener对item做监听,所以可以分离开 * @param v */ @Override public void onClick(View v) { switch (v.getId()){ case R.id.toolbar_btn: if(drawerLayout.isDrawerOpen(Gravity.LEFT)){ //判断一下是否已经开启了,开了关,关了开 drawerLayout.closeDrawer(Gravity.LEFT); }else drawerLayout.openDrawer(Gravity.LEFT); break; default: break; } } }
不需要多解释,代码里有一些注解,就算不看注解也是很好理解的。
OK,最后给大家上一张效果图:
贴一下其他博客的链接,大家可以参考一下:
https://blog.csdn.net/u012702547/article/details/51253222 Android5.0之NavigationView的使用
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0608/3011.html
Design Support Library (I): Navigation View的使用
https://lvwenhan.com/ios/445.html 再造 “手机QQ” 侧滑菜单(一)——实现侧滑效果(这个是IOS,不过有更好看的效果,想研究的同学可以稍微看看)
https://blog.csdn.net/lmj623565791/article/details/39257409 Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭(android版)