Android 如何检测 DrawerLayout 开始打开?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23373257/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:03:50  来源:igfitidea点击:

How to detect that the DrawerLayout started opening?

androidnavigation-drawerdrawerlayoutdrawertoggle

提问by Oleksiy

So I have tabs that I want to hide when the Navigation Drawer startsopening. The code I have hides them when it finished opening, but it's not what I want.

因此,当导航抽屉开始打开时,我想隐藏一些选项卡。我的代码在完成打开时隐藏了它们,但这不是我想要的。

mDrawerToggle = new ActionBarDrawerToggle(
        this,                 
        mDrawerLayout,        
        R.drawable.ic_drawer,  
        R.string.drawer_open,  
        R.string.drawer_close  
) {
    @Override
    public void onDrawerClosed(View view) {
        invalidateOptionsMenu(); 
        setActionBarMode(ActionBar.NAVIGATION_MODE_TABS);
    }

    @Override
    public void onDrawerOpened(View drawerView) {
        invalidateOptionsMenu(); 
        setActionBarMode(ActionBar.NAVIGATION_MODE_STANDARD);
    }

};
mDrawerLayout.setDrawerListener(mDrawerToggle);

Here's what I tried:

这是我尝试过的:

  • Setting an onClickListenerto mDrawerLayout. onClicknever gets called
  • Setting an onTouchListenerto mDrawerLayout. onTouchnever gets called
  • Researched ActionBarDrawerToggleand DrawerLayoutclasses. Could not find anything like onDrawerStartedOpening.
  • 设置onClickListenermDrawerLayoutonClick永远不会被调用
  • 设置onTouchListenermDrawerLayoutonTouch永远不会被调用
  • 研究ActionBarDrawerToggleDrawerLayout上课。找不到类似的东西onDrawerStartedOpening

回答by Pavel Dudka

There are 2 possible ways to do that:

有两种可能的方法来做到这一点:

1) Use onDrawerSlide(View drawerView, float slideOffset)callback

1)使用onDrawerSlide(View drawerView, float slideOffset)回调

slideOffsetchanges from 0 to 1. 1means it is completely open, 0- closed.

slideOffset从 0 变为 1。1表示它完全打开,0- 关闭。

Once offset changes from 0to !0- it means it startedopening process. Something like:

一旦偏移量从0!0- 这意味着它开始打开过程。就像是:

mDrawerToggle = new ActionBarDrawerToggle(
        this,                 
        mDrawerLayout,        
        R.drawable.ic_drawer,  
        R.string.drawer_open,  
        R.string.drawer_close  
) {

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset) {
        if (slideOffset == 0
                && getActionBar().getNavigationMode() == ActionBar.NAVIGATION_MODE_STANDARD) {
            // drawer closed
            getActionBar()
                    .setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            invalidateOptionsMenu();
        } else if (slideOffset != 0
                && getActionBar().getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) {
            // started opening
            getActionBar()
                    .setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
            invalidateOptionsMenu();
        }
        super.onDrawerSlide(drawerView, slideOffset);
    }
};
mDrawerLayout.setDrawerListener(mDrawerToggle);

2) Use onDrawerStateChanged(int newState)callback

2)使用onDrawerStateChanged(int newState)回调

You need to listen to STATE_SETTLINGstates - this state is reported whenever drawer starts moving (either opens or closes). So once you see this state - check whether drawer is opened now and act accordingly:

您需要监听STATE_SETTLING状态 - 每当抽屉开始移动(打开或关闭)时都会报告此状态。因此,一旦您看到此状态 - 检查抽屉现在是否已打开并采取相应措施:

mDrawerToggle = new ActionBarDrawerToggle(
        this,                 
        mDrawerLayout,        
        R.drawable.ic_drawer,  
        R.string.drawer_open,  
        R.string.drawer_close  
) {
    @Override
    public void onDrawerStateChanged(int newState) {
        if (newState == DrawerLayout.STATE_SETTLING) {
            if (!isDrawerOpen()) {
                // starts opening
                getActionBar()
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
            } else {
                // closing drawer
                getActionBar()
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            }
            invalidateOptionsMenu();
        }
    }
};
mDrawerLayout.setDrawerListener(mDrawerToggle);

回答by Kirill Karmazin

Currently accepted answer by Pavel Dudka is already deprecated. Please use mDrawerLayout.addDrawerListener()method instead to set a listener.

Pavel Dudka 目前接受的答案已被弃用。请改用mDrawerLayout.addDrawerListener()方法来设置侦听器。

mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {

        @Override
        public void onDrawerSlide(View drawerView, float slideOffset) {
            //Called when a drawer's position changes.
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            //Called when a drawer has settled in a completely open state.
            //The drawer is interactive at this point.
            // If you have 2 drawers (left and right) you can distinguish 
            // them by using id of the drawerView. int id = drawerView.getId(); 
            // id will be your layout's id: for example R.id.left_drawer            
        }

        @Override
        public void onDrawerClosed(View drawerView) {
            // Called when a drawer has settled in a completely closed state.
        }

        @Override
        public void onDrawerStateChanged(int newState) {
            // Called when the drawer motion state changes. The new state will be one of STATE_IDLE, STATE_DRAGGING or STATE_SETTLING.
        }
    });

Works perfectly. Cheers!

完美运行。干杯!

回答by fookwood

try to override a method of DrawerLayout.DrawerListener

尝试覆盖 DrawerLayout.DrawerListener 的方法

@Override
public void onDrawerStateChanged(int newState) {
    if( newState == DrawerLayout.STATE_DRAGGING && isDrawerOpen() == false ) {
        // this where Drawer start opening
    }
}

回答by NoHarmDan

Up-to-date solution:

最新解决方案:

As others have suggested, the current answer is outdated and it's advised to use mDrawerLayout.addDrawerListener(). A working solution would then be:

正如其他人所建议的那样,当前的答案已经过时,建议使用mDrawerLayout.addDrawerListener(). 一个可行的解决方案是:

mDrawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
        @Override
        public void onDrawerStateChanged(int newState) {
            if (newState == DrawerLayout.STATE_SETTLING && !mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
                // Drawer started opening
            }
        }
    });

Naturally, replace GravityCompat.STARTwith whatever identifies your drawer (layout ID or its gravity ~ location).

自然地,GravityCompat.START用任何标识你的抽屉的东西(布局 ID 或它的重力 ~ 位置)替换。

Also, if you want to detect when the drawer starts closing, you can simply do:

此外,如果您想检测抽屉何时开始关闭,您可以简单地执行以下操作:

mDrawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
        @Override
        public void onDrawerStateChanged(int newState) {
            if (newState == DrawerLayout.STATE_SETTLING) {
                if (!mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
                    // Drawer started opening
                } else {
                    // Drawer started closing
                }
            }
        }
    });

回答by Kishan Solanki

For Kotlin

对于科特林

var toggle = object : ActionBarDrawerToggle(this,
                drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {

            override fun onDrawerOpened(drawerView: View) {
                super.onDrawerOpened(drawerView)
            }
        }
drawer_layout.addDrawerListener(toggle)
toggle.syncState()

回答by Stefano Cristoni

drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close){
      @Override
      public void onDrawerOpened(View drawerView) {
           super.onDrawerOpened(drawerView);
           app.sendScreenView("Menu");
      }
};
drawer.setDrawerListener(toggle);
toggle.syncState();

It's the best way.

这是最好的方法。

回答by bastami82

fookwood answer did not work for me but slight modification in the if statment did the trick)

fookwood 的答案对我不起作用,但在 if 语句中稍作修改即可解决问题)

ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, navigationDrawerLayout, topToolbar,
                R.string.open_drawer, R.string.close_drawer) {
            @Override public void onDrawerStateChanged(int newState) {
                if (newState == DrawerLayout.STATE_SETTLING && !navigationDrawerLayout.isDrawerOpen(navigationDrawerView)) {
                    // this where Drawer start opening
}