【问题标题】:How to prevent closing Navigation drawer by touch outside the drawer如何防止通过触摸抽屉外来关闭导航抽屉
【发布时间】:2015-02-20 10:02:21
【问题描述】:

我有一个带有导航抽屉的活动。如果用户设备是桌子并且方向是横向 - 我不需要通过单击抽屉中的项目来关闭抽屉:

if (!isTablet || context.getResources().getConfiguration().orientation==1) {
    mDrawerLayout.closeDrawer(Gravity.START);
}

它工作。但是如果用户在打开的抽屉外面触摸屏幕 - 抽屉关闭。 使用 DrawerLayout.LOCK_MODE_LOCKED_OPEN 是不合适的,因为我需要保存抽屉滑动功能。 当用户触摸抽屉外时如何防止关闭导航抽屉?

请帮忙。

【问题讨论】:

  • 你知道,这样做违背了Android Guidelines 当导航抽屉展开时,用户可以通过以下四种方式之一将其关闭: 触摸导航抽屉外的内容 滑动到屏幕上任意位置的左侧(包括从右侧滑动) 触摸操作栏中的应用程序图标/标题 按下返回
  • 我同意,用户期望这种行为,当你把它拿走时,他们会生气的。
  • 感谢您的回复。我理解这一点,但这是产品要求。
  • @Anton Stukov 你找到问题的答案了吗?
  • 不,没有找到任何东西。

标签: android touch navigation-drawer


【解决方案1】:

基于我写的另一个答案here。我已经修改了代码以适合您的问题。请检查。

查看有关触摸层次结构的更多信息here

dispatchTouchEvent() 方法应该在 Activity 类中被覆盖

@Override    
public boolean dispatchTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_UP) {
        if (isDrawerOpen()) { //Your code here to check whether drawer is open or not. 

            View content = findViewById(R.id.drawer); //drawer view id
            int[] contentLocation = new int[2];
            content.getLocationOnScreen(contentLocation);
            Rect rect = new Rect(contentLocation[0],
                contentLocation[1],
                contentLocation[0] + content.getWidth(),
                contentLocation[1] + content.getHeight());

            if (!(rect.contains((int) event.getX(), (int) event.getY()))) {
                isOutSideClicked = true;
            } else {
                isOutSideClicked = false;
            }

        } else {
            return super.dispatchTouchEvent(event);
        }
    } else if (event.getAction() == MotionEvent.ACTION_DOWN && isOutSideClicked) {
        isOutSideClicked = false;
        return super.dispatchTouchEvent(event);
    } else if (event.getAction() == MotionEvent.ACTION_MOVE && isOutSideClicked) {
        return super.dispatchTouchEvent(event);
    }

    if (isOutSideClicked) {
        return true; //restrict the touch event here
    }else{
        return super.dispatchTouchEvent(event);
    }
}

注意:正如问题 cmets 中所提到的,这与Android guidelines 相违背。所以尽量避免它,除非它是强制性的。

【讨论】:

    【解决方案2】:

    Noundla 的答案的简化版本对我有用。我编写了自定义 Drawer,它扩展了 DrawerLayout 并实现了 dispatchTouchEvent() 方法。

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (!this.isDrawerOpen(Gravity.LEFT)) {
            return super.dispatchTouchEvent(event);
        }
        boolean isOutSideClicked = false;
        if (event.getAction() == MotionEvent.ACTION_UP) {
            View content = findViewById(R.id.drawer_view); 
            int[] contentLocation = new int[2];
            content.getLocationOnScreen(contentLocation);
            Rect rect = new Rect(contentLocation[0],
                    contentLocation[1],
                    contentLocation[0] + content.getWidth(),
                    contentLocation[1] + content.getHeight());
            isOutSideClicked = !(rect.contains((int) event.getX(), (int) event.getY()));
        }
        this.setDrawerLockMode(isOutSideClicked ? DrawerLayout.LOCK_MODE_LOCKED_OPEN : DrawerLayout.LOCK_MODE_UNLOCKED);
        return super.dispatchTouchEvent(event);
    }
    

    此外,如果您想在抽屉打开时与主要内容片段保持交互,您应该在方法的开头添加这一行。

    getChildAt(0).dispatchTouchEvent(event);
    

    【讨论】:

      【解决方案3】:

      使用您的抽屉实例来防止非常简单

      1.实现 DrawerLayout.DrawerListener

      2。在这个方法中添加这个单一的语句我们

       @Override
      public void onDrawerOpened(View drawerView) {
          drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);//DrawerLayout instance
      }
      

      【讨论】:

      • 这个答案非常有用且使用起来非常简单,只需要处理打开和关闭抽屉的点击操作。当抽屉打开时使用 DrawerLayout.LOCK_MODE_LOCKED_OPEN & 当抽屉关闭时使用 DrawerLayout.LOCK_MODE_LOCKED_CLOSED
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多