zoukankan      html  css  js  c++  java
  • 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() + "
    执行了一次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 

  • 相关阅读:
    pat甲级 1155 Heap Paths (30 分)
    pat甲级 1152 Google Recruitment (20 分)
    蓝桥杯 基础练习 特殊回文数
    蓝桥杯 基础练习 十进制转十六进制
    蓝桥杯 基础练习 十六进制转十进制
    蓝桥杯 基础练习 十六进制转八进制
    51nod 1347 旋转字符串
    蓝桥杯 入门训练 圆的面积
    蓝桥杯 入门训练 Fibonacci数列
    链表相关
  • 原文地址:https://www.cnblogs.com/whycxb/p/8506137.html
Copyright © 2011-2022 走看看