![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISN3gTM1ATN5EjNyUDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
在(一)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版)
Android5.0之NavigationView的使用