1. 程式人生 > >滑動選單DrawerLayout詳解(實時更新,未完待續...)

滑動選單DrawerLayout詳解(實時更新,未完待續...)

前言:目前所寫程式碼都是參照第一行程式碼所寫,但日後專案發現新的應用一定會實時更新。


一,在佈局中引入DrawerLayout
activity_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="match_parent">
    <android.support.v4.widget.DrawerLayout
android:id="@+id/myFirstDrawerLayout" android:layout_width="match_parent" android:layout_height="match_parent">
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar
android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="#1EB9FD" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
</FrameLayout
>
<TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="滑動有驚喜" android:layout_gravity="start" android:background="#1EB9FD"/> </android.support.v4.widget.DrawerLayout> </LinearLayout>

這段程式碼還加入了toolbar,不熟悉可以點我上篇博文,我們來解釋其它部分。我在DrawerLayout內部還加了一個簡單的textView,裡面最重要的一點是layout_gravity屬性,它決定了drawerLayout從哪一邊劃出來。
二,在activity中引入DrawerLayout
先貼整體程式碼
MainActivity.class

package com.example.slidingmenu;

import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
    private Toolbar mToolbar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mToolbar=(Toolbar)findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);//用toolbar替代acitonbar
        ActionBar actionBar=getSupportActionBar();
        if(actionBar!=null){
            actionBar.setDisplayHomeAsUpEnabled(true);//讓導航按鈕顯示
            actionBar.setHomeAsUpIndicator(R.mipmap.navigation);//用自己定義的導航欄圖示代替預設的箭頭圖示
        }
        mDrawerLayout=(DrawerLayout)findViewById(R.id.myFirstDrawerLayout);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home://HomeAsUp按鈕預設固定的名稱
                mDrawerLayout.openDrawer(GravityCompat.START);//傳入你在layout_gravity所填值,我這裡是填了start
        }
        return true;
    }
}

注意這裡的onOptionsItemSelected方法

 @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home://HomeAsUp按鈕預設固定的名稱
                mDrawerLayout.openDrawer(GravityCompat.START);//傳入你在layout_gravity所填值,我這裡是填了start
        }
        return true;
    }

這個是為了實現點選導航按鈕,選單從側面滑出的功能。android.R.id.home是HomeAsUp(即圖中那個圖片按鈕)的預設固定名稱。接著我們向openDrawerf方法中傳入gravity型別引數,注意這裡必須傳入你在佈局檔案中一致的屬性。因為我在activty_main.xml檔案中填的是layout_gravity:”start”,所以這裡保持一致。
這樣我們已經實現了一個最簡單的滑動選單。
當然我們可以自定以佈局,豐富其中的內容,讓它如qq那樣美觀,不過google的大神們已經幫我們鋪好了路。使用NavigationView控制元件可以輕鬆實現qq側滑選單。

三,利用NavigationView定製漂亮的側滑選單

A,新增依賴庫
NavigatonView是Design Support庫所提供,所以我們要在app/build.gradle中引入依賴庫:

    compile "com.android.support:design:25.3.1"
    compile 'de.hdodenhof:circleimageview:2.1.0'

第一行依賴庫就是Design Support,注意sdk版本問題,如果是24則填:24.2.1;25則填:25.3.1;26則填:26.0.2,這些在google官網都可以查到的。第二行依賴庫是一個將任何形狀圖片變為圓形圖片的一個開源庫。
B ,定義menu和headerlayout檔案
NavigationView的使用需要menu和headerlayout兩個佈局檔案,headerlayout即是我們qq的上半部分,通常用來放頭像,menu既是下半部分,提供一些選項。
首先在res中建立menu資料夾,再在menu資料夾中新建menu.xml
menu.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/setting"
        android:icon="@mipmap/setting_item"
        android:title="Setting"/>
    <item
        android:id="@+id/telephone"
        android:icon="@mipmap/call_item"
        android:title="Telephone"/>
</group>
</menu>

其中checkableBehavior=”single”代表item為單選,title代表item的內容。

再在layout資料夾中新建headerlayout.xml
headlayout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:padding="10dp"
    android:orientation="vertical"
    android:background="#1EB9FD">
<de.hdodenhof.circleimageview.CircleImageView
    android:id="@+id/headPortrait"
    android:layout_width="70dp"
    android:layout_height="70dp"
    android:src="@drawable/head_portrait"
    android:layout_centerInParent="true"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="吃著冰淇凌望著藍天"
        android:layout_alignParentBottom="true"/>
</RelativeLayout>

這個很簡單,放入頭像圖片和一段文字。
C,在佈局中引入NavigationView
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v4.widget.DrawerLayout
        android:id="@+id/myFirstDrawerLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="#1EB9FD"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
        </FrameLayout>
        <android.support.design.widget.NavigationView
            android:id="@+id/mFirstNavigationView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            app:menu="@menu/menu"
            app:headerLayout="@layout/headlayout"/>

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

其中menu和headerlayout分別對應我們之前建立的兩個佈局檔案。
D,可以在activity中為NavigationView的item新增點選事件
MainActivity.class

package com.example.slidingmenu;

import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
    private Toolbar mToolbar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mToolbar=(Toolbar)findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);//用toolbar替代acitonbar
        ActionBar actionBar=getSupportActionBar();
        if(actionBar!=null){
            actionBar.setDisplayHomeAsUpEnabled(true);//讓導航按鈕顯示
            actionBar.setHomeAsUpIndicator(R.mipmap.navigation);//用自己定義的導航欄圖示代替預設的箭頭圖示
        }
        mDrawerLayout=(DrawerLayout)findViewById(R.id.myFirstDrawerLayout);
        NavigationView mNavigationView=(NavigationView)findViewById(R.id.mFirstNavigationView);
        mNavigationView.setCheckedItem(R.id.setting);
        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                mDrawerLayout.closeDrawers();//關閉側滑選單
                return true;
            }
        });
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home://HomeAsUp按鈕預設固定的名稱
                mDrawerLayout.openDrawer(GravityCompat.START);//傳入你在layout_gravity所填值,我這裡是填了start
        }
        return true;
    }
}

主要看如下程式碼

 mNavigationView.setCheckedItem(R.id.setting);

設定預設選中的item。

mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                mDrawerLayout.closeDrawers();//關閉側滑選單
                return true;
            }
        });

為每個item新增監聽,點選Item後關閉側滑選單,這部分可以類比button等控制元件點選事件來理解。
E,為NavigationView的headerLayout新增點選事件
很奇怪官方為什麼不寫個headerLayout監聽事件的封裝,但即使這樣我們還是有辦法做到。
下面是一種可行的方法:
MainActivity.class

View headerLayout=mNavigationView.inflateHeaderView(R.layout.headlayout);
        CircleImageView headPortrait=(CircleImageView)headerLayout.findViewById(R.id.headPortrait);
        headPortrait.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view){
                Toast.makeText(MainActivity.this, "你點選了頭像", Toast.LENGTH_SHORT).show();
            }
        });

注意這樣寫,headerLayout會載入兩遍,因為其中的inflate方法。所以要在activity_main.xml先去除headerlayout:

app:headerlayout="@layout/headlayout"

還有另一種方法,不用去除,只需把`

View headerLayout=mNavigationView.inflateHeaderView(R.layout.headlayout);

換成

View headerLayout=mNavigationView.getHeaderView(0);

經過以上步驟相信大家都能做出一個漂亮的側滑選單。