How to prevent closing Navigation drawer by touch outside the drawer

孤街浪徒 提交于 2019-11-29 14:17:43
Noundla Sandeep

Based on the other answer which I wrote here. I have modified the code to suit your question. Please check.

Check more about touch hierarchy here

dispatchTouchEvent() method should be overridden in Activity class

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

Note: As mentioned in the question comments, this is against of Android guidelines. So try to avoid it until unless it is mandatory.

Simplified version of Noundla's answer which works for me. I wrote my custom Drawer which extends DrawerLayout and implement dispatchTouchEvent() method.

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

Also if you want to keep interact with main content fragment while drawer is open you should add this line at the beginning of the method.

getChildAt(0).dispatchTouchEvent(event);

it very simple use your drawer instance to prevent

1. implement DrawerLayout.DrawerListener

2. add this single statement inside this method us

 @Override
public void onDrawerOpened(View drawerView) {
    drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);//DrawerLayout instance
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!