1 DrawerLayout界面点击事件穿透问题,即点击Drawerlayout上面的区域,会发现该位置DrawerLayout覆盖掉的区域的控件可以被点击 解决方案如下:
//这里设置clickable(true) 必须动态设置 静态设置没有效果
//解决问题 侧滑菜单出来的时候 点击菜单上的区域会有点击穿透问题
mDrawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
}
@Override
public void onDrawerOpened(View drawerView) {
drawerView.setClickable(true);
}
@Override
public void onDrawerClosed(View drawerView) {
}
@Override
public void onDrawerStateChanged(int newState) {
}
});
- 处理DrawerLayout全屏滑动(默认不会全屏滑动)、然后屏蔽掉长按会弹抽屉的方式
/**
* 向右边滑
* 处理DrawerLayout全屏滑动(默认不会全屏滑动)、然后屏蔽掉长按会弹抽屉的方式
* @param displayWidthPercentage 1.0表示全屏可滑动 0.5只有右半部分可滑屏 0表示没有滑动事件
*/
fun setDrawerRightEdgeSize(
activity: Activity,
drawerLayout: DrawerLayout,
displayWidthPercentage: Float
) {
if (activity == null || drawerLayout == null) return
try {
// 找到 ViewDragHelper 并设置 Accessible 为true
val leftDraggerField: Field =
drawerLayout.javaClass.getDeclaredField("mLeftDragger") //Right
// true表示可全屏滑动
leftDraggerField.isAccessible = true
val leftDragger: ViewDragHelper = leftDraggerField[drawerLayout] as ViewDragHelper
// 找到 edgeSizeField 并设置 Accessible 为true
val edgeSizeField: Field = leftDragger.javaClass.getDeclaredField("mEdgeSize")
// true表示可全屏滑动
edgeSizeField.isAccessible = true
val edgeSize = edgeSizeField.getInt(leftDragger)
// 设置新的边缘大小
val displaySize = Point()
activity.windowManager.defaultDisplay.getSize(displaySize)
edgeSizeField.setInt(
leftDragger, Math.max(
edgeSize, (displaySize.x *
displayWidthPercentage).toInt()
)
)
//获取 Layout 的 ViewDragCallBack 实例“mLeftCallback”
//更改其属性 mPeekRunnable
val leftCallbackField: Field =
drawerLayout.javaClass.getDeclaredField("mLeftCallback")
// true 表示不可长按弹窗
leftCallbackField.isAccessible = true
//因为无法直接访问私有内部类,所以该私有内部类实现的接口非常重要,通过多态的方式获取实例
val leftCallback: ViewDragHelper.Callback =
leftCallbackField[drawerLayout] as ViewDragHelper.Callback
val peekRunnableField: Field = leftCallback.javaClass.getDeclaredField("mPeekRunnable")
// true 表示不可长按弹窗
peekRunnableField.isAccessible = true
peekRunnableField[leftCallback] = Runnable {}
} catch (e: NoSuchFieldException) {
} catch (e: IllegalArgumentException) {
} catch (e: IllegalAccessException) {
}
}
- Android中DrawerLayout+ViewPager滑动冲突及类似侧滑抽屉内列表数据条目侧滑冲突的解决方法
首先,让我们先来解决 DrawerLayout 和 ViewPager 的侧滑事件冲突。当 DrawerLayout 中嵌套 ViewPager 时,侧滑默认是执行 DrawerLayout 的侧滑事件,因为 Android 的事件分发是从 外层 ViewGroup 向里逐级传递到 View 的。
所以会先执行 DrawerLayout 的 onTouchEvent 方法:
@Override
public boolean onTouchEvent(MotionEvent ev) {
mLeftDragger.processTouchEvent(ev);
mRightDragger.processTouchEvent(ev);
final int action = ev.getAction(); boolean wantTouchEvents = true;
switch (action & MotionEventCompat.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mInitialMotionX = x;
mInitialMotionY = y;
mDisallowInterceptRequested = false;
mChildrenCanceledTouch = false;
break;
}
case MotionEvent.ACTION_UP: {
final float x = ev.getX();
final float y = ev.getY();
boolean peekingOnly = true;
final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y);
if (touchedView != null && isContentView(touchedView)) {
final float dx = x - mInitialMotionX;
final float dy = y - mInitialMotionY;
final int slop = mLeftDragger.getTouchSlop();
if (dx * dx + dy * dy < slop * slop) {
// Taps close a dimmed open drawer but only if it isn't locked open.
final View openDrawer = findOpenDrawer();
if (openDrawer != null) {
peekingOnly = getDrawerLockMode(openDrawer) == LOCK_MODE_LOCKED_OPEN;
}
}
}
closeDrawers(peekingOnly);
mDisallowInterceptRequested = false;
break;
}
case MotionEvent.ACTION_CANCEL: {
closeDrawers(true);
mDisallowInterceptRequested = false;
mChildrenCanceledTouch = false; break;
}
}
return wantTouchEvents;
}
可以看到在最后始终返回 wantTouchEvents,也就是返回 true,意味着点击事件在 DrawerLayout 就被消费掉了,无法传到 ViewPager。
所以,我们像下面这样,监听当 Drawer 打开时,将 DrawerLayout 设置为 LOCK_MODE_LOCKED_OPEN,这样在 Drawer 被打开时,就能够触发 ViewPager 的滑动事件了。
mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
}
@Override
public void onDrawerOpened(View drawerView) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
}
@Override public void onDrawerClosed(View drawerView) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
}
@Override public void onDrawerStateChanged(int newState) {
}
});
但是,当侧边栏的 ViewPager 滑动到最后一页,再向左滑动时,我们会希望能够自然的关闭 Drawer。这就需要我们监听 ViewPager 的 PageChange 事件,当滑动到最后一页时,将 DrawerLayout 的 LockMode 设置回 LOCK_MODE_UNLOCKED。
然后让 MainActivity 实现这个:
@Override
public void onPageSelected(boolean isLast) {
if (isLast) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
} else if (mDrawerLayout.getDrawerLockMode(GravityCompat.START) == DrawerLayout.LOCK_MODE_UNLOCKED) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
}
}
网友评论