DrawerLayout去除阴影,阴影点击不关闭抽屉,屏蔽触发相关view,抽屉侧滑关闭响应

本文详细介绍了一种定制化的侧滑菜单实现方案,通过重写DrawerLayout,实现了点击阴影区域时抽屉不关闭、仅点击侧边栏按钮才收起抽屉、禁止手势滑动控制抽屉等功能,同时确保主Activity的其他控件在抽屉打开状态下不可点击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,点击阴影位置 抽屉不关闭
2,只有点击侧边栏里面的按钮 才会收起抽屉
3,禁止手势滑动 划出和关闭抽屉功能
/**

  • mainActivty 的其他控件在抽屉打开的情况下不可以点击
    */

drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
//去除侧滑栏阴影
drawer.setScrimColor(Color.TRANSPARENT);
// 禁止手势滑动关闭和打开
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);

    //返回键处理
@Override
public void onBackPressed() {
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}

/**
* 当MainActivity 下方有列表的时候,滑动也会关闭抽屉 次方法就是屏蔽这个的
* @param ev 动作
* @return 重写弗雷方法
*/
// 当抽屉打开时 列表不可滑动
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_MOVE && drawer.isDrawerOpen(GravityCompat.START)) {
return true; // 禁止滑动
}
return super.dispatchTouchEvent(ev);
}

/**

  • 自定义 DrawerLayout 重写onInterceptTouchEvent 当点击的时候,
  • 判断点击位置是否位于相应的View内 如果位于 则响应点击事件
  •                             否则,响应事件传递下去至mainactivity
    

/
/
*
* 判断点击位置是否位于相应的View内
* @param x x坐标
* @param y y坐标
* @return 返回当前view
*/
public View findTopChildUnder(int x, int y) {
final int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i–) {
final View child = getChildAt(i);
if (x >= child.getLeft() && x < child.getRight() &&
y >= child.getTop() && y < child.getBottom()) {
return child;
}
}
return null;
}

/**
 * 判断点击触摸点的View是否是ContentView(即是主页面的View)
 * @param child 子view
 * @return  boolean
 */
boolean isContentView(View child) {
    return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
}

/**
 * 判断点击触摸点的View是否是DrawerView(即是侧边栏的View)
 * @param child  子view
 * @return  boolean
 */
boolean isDrawerView(View child) {
    final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
    final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
            ViewCompat.getLayoutDirection(child));
    if ((absGravity & Gravity.LEFT) != 0) {
        // This child is a left-edge drawer
        return true;
    }
    if ((absGravity & Gravity.RIGHT) != 0) {
        // This child is a right-edge drawer
        return true;
    }
    return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev){
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
final float x = ev.getX();
final float y = ev.getY();
final View touchedView = findTopChildUnder((int) x, (int) y);
if (touchedView != null && isContentView(touchedView)
&& this.isDrawerOpen(GravityCompat.START)) {
return false;
}
}
return super.onInterceptTouchEvent(ev);
}

下面贴出完整每个类及布局文件的源码:

MainActivity

`package com.demo.jack.testdrawerlayout;

import android.graphics.Color;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**

  • mainActivty 的其他控件在抽屉打开的情况下不可以点击
    */
    public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {

    private Button btn1;

    private Button btn2;

    private TextView tv;

    private DrawerLayout drawer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv = (TextView) findViewById(R.id.tv);
    tv.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    if (!drawer.isDrawerOpen(GravityCompat.START)) {
    Toast.makeText(MainActivity.this, “点击了TextView!!!”, Toast.LENGTH_SHORT).show();
    }
    if (!drawer.isDrawerOpen(GravityCompat.START)) {
    drawer.openDrawer(GravityCompat.START);
    }
    }
    });
    btn1 = (Button) findViewById(R.id.btn1);
    btn1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    if (!drawer.isDrawerOpen(GravityCompat.START)) {
    Toast.makeText(MainActivity.this, “点击了Button1”, Toast.LENGTH_SHORT).show();
    }
    }
    });

     btn2 = (Button) findViewById(R.id.btn2);
     btn2.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             if (!drawer.isDrawerOpen(GravityCompat.START)) {
                 Toast.makeText(MainActivity.this, "点击了Button2------", Toast.LENGTH_SHORT).show();
             }
         }
     });
    
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
     setSupportActionBar(toolbar);
     drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
     drawer.setScrimColor(Color.TRANSPARENT);
     // 禁止手势滑动
     drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
     ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
             this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
     drawer.setDrawerListener(toggle);
     toggle.syncState();
    
     NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
     navigationView.setNavigationItemSelectedListener(this);
    

    }
    //返回键处理
    @Override
    public void onBackPressed() {
    if (drawer.isDrawerOpen(GravityCompat.START)) {
    drawer.closeDrawer(GravityCompat.START);
    } else {
    super.onBackPressed();
    }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

     //noinspection SimplifiableIfStatement
     if (id == R.id.action_settings) {
         return true;
     }
    
     return super.onOptionsItemSelected(item);
    

    }

    @SuppressWarnings(“StatementWithEmptyBody”)
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

     if (id == R.id.nav_camera) {
         // Handle the camera action
     } else if (id == R.id.nav_gallery) {
    
     } else if (id == R.id.nav_slideshow) {
    
     } else if (id == R.id.nav_manage) {
    
     } else if (id == R.id.nav_share) {
    
     } else if (id == R.id.nav_send) {
    
     }
     //只有点击侧边栏里面的按钮 才会收起抽屉
     if (drawer.isDrawerOpen(GravityCompat.START)) {
         drawer.closeDrawer(GravityCompat.START);
     }
     Toast.makeText(MainActivity.this
             , "点击了侧边栏---->" + item.getTitle(), Toast.LENGTH_SHORT).show();
     return true;
    

    }

    /**

    • 当MainActivity 下方有列表的时候,滑动也会关闭抽屉 次方法就是屏蔽这个的
    • @param ev 动作
    • @return 重写弗雷方法
      */
      // 当抽屉打开时 列表不可滑动
      @Override
      public boolean dispatchTouchEvent(MotionEvent ev) {
      if (ev.getAction() == MotionEvent.ACTION_MOVE && drawer.isDrawerOpen(GravityCompat.START)) {
      return true; // 禁止滑动
      }
      return super.dispatchTouchEvent(ev);
      }
      }
      布局文件: activity_main<?xml version="1.0" encoding="utf-8"?>
      <com.demo.jack.testdrawerlayout.CustomDrawerLayout 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”>
<RelativeLayout
    android:id="@+id/rl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv"
        android:layout_marginTop="20dp"
        android:text="打开侧滑栏"
        android:layout_marginRight="20dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn1"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:text="Button1"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn2"
        android:layout_below="@id/btn1"
        android:layout_alignParentRight="true"
        android:text="Button2"/>

</RelativeLayout>

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="150dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer" />

</com.demo.jack.testdrawerlayout.CustomDrawerLayout>
mainactivity 布局文件中的 nav_header_main 布局文件<?xml version="1.0" encoding="utf-8"?>
<com.demo.jack.testdrawerlayout.CustomDrawerLayout 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”>

<RelativeLayout
    android:id="@+id/rl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv"
        android:layout_marginTop="20dp"
        android:text="打开侧滑栏"
        android:layout_marginRight="20dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn1"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:text="Button1"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn2"
        android:layout_below="@id/btn1"
        android:layout_alignParentRight="true"
        android:text="Button2"/>

</RelativeLayout>

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="150dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer" />

</com.demo.jack.testdrawerlayout.CustomDrawerLayout>
`

最重要的 自定义 CustomDrawerLayout 类文件

`package com.demo.jack.testdrawerlayout;

import android.content.Context;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;

/**

  • 自定义 DrawerLayout 重写onInterceptTouchEvent 当点击的时候,判断是否是
    */
    public class CustomDrawerLayout extends DrawerLayout {

    public CustomDrawerLayout(Context context){
    this(context, null);
    }

    public CustomDrawerLayout(Context context,AttributeSet attrs) {
    this(context, attrs, 0);
    }

    public CustomDrawerLayout(Context context,AttributeSet attrs, int defStyle) {
    super(context, attrs,defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev){
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
    final float x = ev.getX();
    final float y = ev.getY();
    final View touchedView = findTopChildUnder((int) x, (int) y);
    if (touchedView != null && isContentView(touchedView)
    && this.isDrawerOpen(GravityCompat.START)) {
    return false;
    }
    }
    return super.onInterceptTouchEvent(ev);
    }

    /**

    • 判断点击位置是否位于相应的View内
    • @param x x坐标
    • @param y y坐标
    • @return 返回当前view
      */
      public View findTopChildUnder(int x, int y) {
      final int childCount = getChildCount();
      for (int i = childCount - 1; i >= 0; i–) {
      final View child = getChildAt(i);
      if (x >= child.getLeft() && x < child.getRight() &&
      y >= child.getTop() && y < child.getBottom()) {
      return child;
      }
      }
      return null;
      }

    /**

    • 判断点击触摸点的View是否是ContentView(即是主页面的View)
    • @param child 子view
    • @return boolean
      */
      boolean isContentView(View child) {
      return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
      }

    /**

    • 判断点击触摸点的View是否是DrawerView(即是侧边栏的View)
    • @param child 子view
    • @return boolean
      */
      boolean isDrawerView(View child) {
      final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
      final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
      ViewCompat.getLayoutDirection(child));
      if ((absGravity & Gravity.LEFT) != 0) {
      // This child is a left-edge drawer
      return true;
      }
      if ((absGravity & Gravity.RIGHT) != 0) {
      // This child is a right-edge drawer
      return true;
      }
      return false;
      }

}
布局文件:activity_main_drawer<?xml version="1.0" encoding="utf-8"?>

<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>
` 布局文件: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”
android:fitsSystemWindows=“true”
android:clickable=“true”
tools:context=“com.demo.jack.testdrawerlayout.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"
    android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>
`

如需源码,可留言发你。
如有问题还需大神留言,一块探讨解决

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值