DrawerLayoutDemo【側邊欄(側滑菜單)簡單實現】

版權聲明:本文爲HaiyuKing原創文章,轉載請註明出處!java

前言

簡單實現側邊欄(側滑菜單)效果:android

  • 點擊觸發打開左側側邊欄,手勢滑動關閉左側側邊欄;
  • 手勢滑動打開右側側邊欄,手勢滑動關閉右側側邊欄;
  • 簡單實現打開側邊欄的動畫效果(透明度、移動效果);
  • 打開側邊欄的時候動態更改側邊欄中的數據;

效果圖

             

代碼分析

此Demo只是簡單實現側邊欄的效果,目的在於能夠快速的導入到項目中。至於更復雜的效果,請閱讀《參考資料》git

使用步驟

1、項目組織結構圖

注意事項:github

一、  導入類文件後須要change包名以及從新import R文件路徑網絡

二、  Values目錄下的文件(strings.xml、dimens.xml、colors.xml等),若是項目中存在,則複製裏面的內容,不要整個覆蓋app

2、導入步驟

引入依賴庫

在APP的build.gradle文件中添加如下代碼:ide

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.why.project.drawerlayoutdemo"
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    //DrawerLayout側邊欄中動畫效果用到的 compile 'com.nineoldandroids:library:2.4.0'
}

在styles.xml文件中註釋和添加如下代碼:【主要是用於Demo中的使用自定義的頂部導航欄效果】

<resources>

    <!-- Base application theme. -->
    <!--<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> &lt;!&ndash; Customize your theme here. &ndash;&gt; <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>-->

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

3、使用方法

在Activity佈局文件中使用DrawerLayout【注意下面底色標記的代碼】

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

    <!-- 主內容視圖必定要是DrawerLayout的第一個子視圖【必須】 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- 引入導航欄 -->
        <include
            android:id="@+id/main_navbar"
            layout="@layout/navigationbar_main" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="內容區域"
            android:textSize="22sp"
            android:layout_gravity="center"/>

    </LinearLayout>

    <!-- 左側區域側邊欄【可選】若是想要只有一個右側的側邊欄,那麼就只須要留一個便可,注意的是left須要換成right-->
    <!-- android:tag="LEFT"用於java代碼中經過drawerView.getTag()判斷左側仍是右側 -->
    <fragment
        android:id="@+id/fragment_leftmenu"
        android:name="com.why.project.drawerlayoutdemo.MainMenuLeftFragment"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="left"
        android:tag="LEFT" />

    <!-- 右側區域側邊欄【可選】 -->
    <fragment
        android:id="@+id/fragment_rightmenu"
        android:name="com.why.project.drawerlayoutdemo.MainMenuRightFragment"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="right"
        android:tag="Right" />

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

頂部菜單欄佈局文件navigationbar_main.xml【佈局較簡單,就不展開了】

<?xml version="1.0" encoding="utf-8"?>
<!-- 首頁界面的導航欄佈局文件 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/nav_twoversion_home"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:layout_gravity="center"
    android:background="#3F51B5" >

    <!-- 用戶側邊欄圖標 -->
    <ImageView
        android:id="@+id/nav_user"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:contentDescription="@string/app_name"
        android:gravity="center"
        android:src="@drawable/nav_user" />

    <!-- 標題 -->
    <TextView
        android:id="@+id/nav_title"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="@string/app_name"
        android:textColor="#ffffff"
        android:textSize="18sp" />

</RelativeLayout>
navigationbar_main.xml

建立側邊欄碎片文件——MainMenuLeftFragment、MainMenuRightFragment【根據項目實際需求,可能只須要建立一個便可】【可參考demo中,直接複製到實際項目中,注意修改activity佈局文件中的fragment的完整路徑地址】

MainMenuLeftFragment.java函數

package com.why.project.drawerlayoutdemo;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * Created by HaiyuKing
 * Used 首頁左側側邊欄碎片界面
 */

public class MainMenuLeftFragment extends Fragment {
    private static final String TAG = "MainMenuLeftFragment";
    /**View實例*/
    private View myView;
    //
    private TextView tv_show;

    //重寫
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG,"onCreateView");
        myView = inflater.inflate(R.layout.fragment_home_left_menu, container, false);

        return myView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG,"onActivityCreated");
        //初始化控件以及設置
        initView();
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG,"onResume");
        //初始化監聽事件
        initEvent();
    }

    /**初始化控件*/
    private void initView(){
        Log.d(TAG,"initView");
        tv_show = myView.findViewById(R.id.tv_show);
    }

    /**初始化默認數據【這個須要在activity中執行,緣由是:在佈局文件中經過<fragment>的方式引用Fragment,打開Activity的時候,Fragment的生命週期函數均執行了】
     * 那麼就存在一個問題,初始化fragment中的數據,可能會在activity數據初始化以前執行*/
   public void setDefaultDatas(){ tv_show.setText(tv_show.getText() + "\n執行了一次setDefaultDatas()"); } /**初始化監聽事件*/
    private void initEvent(){

    }
}

fragment_home_left_menu.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:orientation="vertical"
    android:background="#E3E3E3">
    <TextView
        android:id="@+id/tv_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="左側側邊欄區域"
        android:textSize="18sp"
        />
</LinearLayout>

在Activity中使用以下【繼承FragmentActivity或者其子類AppCompatActivity】

package com.why.project.drawerlayoutdemo;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;

import com.nineoldandroids.view.ViewHelper;

public class MainActivity extends AppCompatActivity {

    private Context mContext;

    /**導航欄左側的用戶圖標*/
    private ImageView nav_userImg;

    /**導航欄左側的側邊欄的父容器*/
    private DrawerLayout mDrawerLayout; /**導航欄左側的側邊欄碎片界面*/
    private MainMenuLeftFragment leftMenuFragment;

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

        mContext = this;
        //初始化控件
        initViews();
        //初始化數據
        initData();
        //初始化控件的點擊事件
        initEvent();
    }

    private void initViews() {
        nav_userImg = (ImageView) findViewById(R.id.nav_user);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.id_drawerLayout); //關閉手勢滑動:DrawerLayout.LOCK_MODE_LOCKED_CLOSED(Gravity.LEFT:表明左側的)
 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT); leftMenuFragment = (MainMenuLeftFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_leftmenu);
    }

    private void initData() {

    }

    private void initEvent() {
        //用戶圖標的點擊事件
        nav_userImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                OpenLeftMenu();
            }
        });

        //側邊欄的事件監聽
        mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener()
        {
            /**
             * 當抽屜滑動狀態改變的時候被調用
             * 狀態值是STATE_IDLE(閒置-0),STATE_DRAGGING(拖拽-1),STATE_SETTLING(固定-2)中之一。
             */
            @Override
            public void onDrawerStateChanged(int newState)
            {
            }
            /**
             * 當抽屜被滑動的時候調用此方法
             * slideOffset 表示 滑動的幅度(0-1)
             */
            @Override
            public void onDrawerSlide(View drawerView, float slideOffset)
            {
                Log.w("onDrawerSlide", "slideOffset="+slideOffset);//0.0 -- 0.56 -- 1.0

                View mContent = mDrawerLayout.getChildAt(0);//內容區域view
                View mMenu = drawerView;

                float scale = 1 - slideOffset;

                if (drawerView.getTag().equals("LEFT")) {//左側的側邊欄動畫效果 //設置左側區域的透明度0.6f + 0.4f * (0.0 ... 1.0)【也就是打開的時候透明度從0.6f ... 1.0f,關閉的時候反之】
                    ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * slideOffset); //移動內容區域:左側側邊欄寬度 * (0.0 ... 1.0)【也就是打開的時候,內容區域移動從0 ... 左側側邊欄寬度】
                    ViewHelper.setTranslationX(mContent,mMenu.getMeasuredWidth() * slideOffset); mContent.invalidate();//重繪view
 } else
                {//右側的側邊欄動畫效果
                    //移動內容區域:-右側側邊欄寬度 * (0.0 ... 1.0)【也就是打開的時候,內容區域移動從-0 ... -左側側邊欄寬度】
                    ViewHelper.setTranslationX(mContent,-mMenu.getMeasuredWidth() * slideOffset); mContent.invalidate();
                }

            }
            /**
             * 當一個抽屜被徹底打開的時候被調用
             */
            @Override
            public void onDrawerOpened(View drawerView) {
                if (drawerView.getTag().equals("LEFT")){//若是感受顯示有延遲的話,能夠放到nav_userImg的點擊事件監聽中執行
                    leftMenuFragment.setDefaultDatas();//打開的時候初始化默認數據【好比:請求網絡,獲取數據】
 }
            }
            /**
             * 當一個抽屜被徹底關閉的時候被調用
             */
            @Override
            public void onDrawerClosed(View drawerView)
            {
                //關閉手勢滑動:DrawerLayout.LOCK_MODE_LOCKED_CLOSED(Gravity.LEFT:表明左側的)
 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT);
            }
        });
    }

    /**打開左側的側邊欄*/
    public void OpenLeftMenu() { mDrawerLayout.openDrawer(Gravity.LEFT); //打開手勢滑動:DrawerLayout.LOCK_MODE_UNLOCKED(Gravity.LEFT:表明左側的)
 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED,Gravity.LEFT); }
}

混淆配置

gradle

參考資料

Android DrawerLayout 高仿QQ5.2雙向側滑菜單

DrawerLayout

項目demo下載地址

https://github.com/haiyuKing/DrawerLayoutDemo 

相關文章
相關標籤/搜索