DrawerLayoutDemo【侧边栏(侧滑菜单)简单实现】

版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

简单实现侧边栏(侧滑菜单)效果:

  • 点击触发打开左侧侧边栏,手势滑动关闭左侧侧边栏;
  • 手势滑动打开右侧侧边栏,手势滑动关闭右侧侧边栏;
  • 简单实现打开侧边栏的动画效果(透明度、移动效果);
  • 打开侧边栏的时候动态更改侧边栏中的数据;

效果图

             

代码分析

此Demo只是简单实现侧边栏的效果,目的在于可以快速的导入到项目中。至于更复杂的效果,请阅读《参考资料》

使用步骤

一、项目组织结构图

注意事项:

1、  导入类文件后需要change包名以及重新import R文件路径

2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤

引入依赖库

在APP的build.gradle文件中添加以下代码:

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>

三、使用方法

在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);
    }
}

混淆配置

参考资料

Android DrawerLayout 高仿QQ5.2双向侧滑菜单

DrawerLayout

项目demo下载地址

https://github.com/haiyuKing/DrawerLayoutDemo 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DrawerLayout的封装,对于菜单是ListView的应用来说,这个库提供了更直接的使用方式,你不再需要去写menu的布局,如果你对DrawerLayout使用没有信心,这个库使用起来可能会让你觉得简单些。项目地址:https://github.com/Arasthel/GoogleNavigationDrawerMenu效果图:如何使用方法1. 直接用java代码创建   1. 首先你需要创建个内容页的布局文件<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"                 xmlns:tools="http://schemas.android.com/tools"                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:paddingLeft="@dimen/activity_horizontal_margin"                 android:paddingRight="@dimen/activity_horizontal_margin"                 android:paddingTop="@dimen/activity_vertical_margin"                 android:paddingBottom="@dimen/activity_vertical_margin"                 tools:context="com.dexafree.googlenavigationdrawermenusample.MainActivity">         <TextView                 android:text="Hello world!"                 android:layout_width="wrap_content"                 android:layout_height="wrap_content" /> </RelativeLayout>   2. 创建菜单实例  mDrawer = new GoogleNavigationDrawer(this);   mDrawer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));      3. 创建菜单项  mDrawer.setListViewSections(new String[]{"Section A", "Section B", "Section C"}, // Main sections         new String[]{"Settings01", "Settings02"}, // Secondary sections         new int[]{R.drawable.ic_launcher}, // Main sections icon ids         null);   4. 设置内容页LayoutInflater inflater = getLayoutInflater(); View contentView = inflater.inflate(R.layout.main_content, null); mDrawer.addView(contentView, 0);  5. 设置选择监听器mDrawer.setOnNavigationSectionSelected(new GoogleNavigationDrawer.OnNavigationSectionSelected() {     @Override     public void onSectionSelected(View v, int i, long l) {           Toast.makeText(getBaseContext(), "Selected section: " i, Toast.LENGTH_SHORT).show();      } });   6. 最后将菜单附加到页面上setContentView(mDrawer);  方法2. 在xml中创建菜单实例及内容页<org.arasthel.googlenavdrawermenu.views.GoogleNavigationDrawer xmlns:android="http://schemas.android.com/apk/res/android"xmlns:drawer="http://schemas.android.com/apk/res-auto"android:id="@ id/navigation_drawer_container"android:layout_width="match_parent"android:layout_height="match_parent"drawer:list_paddingTop="?android:actionBarSize"drawer:drawer_gravity="start"drawer:list_mainSectionsEntries="@array/navigation_main_sections"drawer:list_secondarySectionsEntries="@array/navigation_secondary_sections"drawer:list_mainSectionsDrawables="@array/drawable_ids"drawer:list_secondarySectionsDrawables="@array/drawable_ids">   <FrameLayout       android:id="@ id/content_layout"       android:layout_width="match_parent"       android:layout_height="match_parent"/> </org.arasthel.googlenavdrawermenu.views.GoogleNavigationDrawer>  接下来就按照方法1的步骤3、步骤5.
drawerlayout是Android提供的一个布局容器,用于实现侧边栏的功能。下面是使用drawerlayout实现侧边栏的步骤: 1. 在XML布局文件中,添加DrawerLayout作为根布局,然后在DrawerLayout中添加两个子布局,侧边栏布局和内容布局。例如: ```xml <androidx.drawerlayout.widget.DrawerLayout android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 侧边栏布局 --> <LinearLayout android:id="@+id/navigation_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:background="@color/colorAccent" android:orientation="vertical"> <!-- 侧边栏内容 --> </LinearLayout> <!-- 内容布局 --> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 内容 --> </FrameLayout> </androidx.drawerlayout.widget.DrawerLayout> ``` 2. 在Activity中,找到DrawerLayout并设置其监听器,用于控制侧边栏的显示和隐藏。例如: ```java DrawerLayout drawerLayout = findViewById(R.id.drawer_layout); NavigationView navigationView = findViewById(R.id.navigation_drawer); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawerLayout.addDrawerListener(toggle); toggle.syncState(); navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { // 处理侧边栏菜单项的点击事件 drawerLayout.closeDrawer(GravityCompat.START); return true; } }); ``` 3. 使用NavigationView来填充侧边栏布局,并设置菜单项的点击事件监听器。例如: ```java NavigationView navigationView = findViewById(R.id.navigation_drawer); navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { // 处理侧边栏菜单项的点击事件 drawerLayout.closeDrawer(GravityCompat.START); return true; } }); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值