63

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

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

这是我尝试过的:

  • 设置onClickListenermDrawerLayout. onClick永远不会被调用
  • 设置onTouchListenermDrawerLayout. onTouch永远不会被调用
  • 研究ActionBarDrawerToggleDrawerLayout上课。找不到类似的东西onDrawerStartedOpening
4

8 回答 8

86

已弃用:查看其他答案以获得更合适的解决方案

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

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

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

一旦偏移量从0to 变为!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);
  1. 使用onDrawerStateChanged(int newState)回调

您需要监听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);
于 2014-04-29T19:26:37.487 回答
46

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

完美运行。干杯!

于 2017-04-03T12:20:48.623 回答
12

尝试覆盖 DrawerLayout.DrawerListener 的方法

@Override
public void onDrawerStateChanged(int newState) {
    if( newState == DrawerLayout.STATE_DRAGGING && isDrawerOpen() == false ) {
        // this where Drawer start opening
    }
}
于 2014-04-29T19:28:08.663 回答
11

最新解决方案:

正如其他人所建议的那样,当前的答案已经过时,建议使用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
            }
        }
    });

自然,GravityCompat.START用任何标识您的抽屉(布局 ID 或其重力〜位置)替换。

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

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
                }
            }
        }
    });
于 2018-06-29T12:22:12.240 回答
10

对于科特林

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()
于 2018-11-12T10:17:42.143 回答
1
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();

这是最好的方法。

于 2017-05-23T15:52:38.650 回答
1

我不明白为什么这里几乎每个人都建议使用沉降,而在抽屉沉降时调用它,所以在开始打开时没有?这个问题不是很清楚吗?

如何检测 DrawerLayout 开始打开?

然后我不明白人们如何建议在使用带有 slideOffset 的简单回调时重复调用未知次数直到打开完成的代码,这可能会导致一些未知问题,具体取决于您的实现,它只会浪费性能。您只想知道抽屉什么时候开始打开并且知道一次,而不是 100 次...

我不认为这是超级简单的解决方案,但我正在这样实现它:

val DrawerLayout.isDrawerOpen get() = isDrawerOpen(START) || isDrawerOpen(END)

fun DrawerLayout.onDrawerOpening(function: (DrawerLayout) -> Unit) {
    val drawerLayout = this
    var onDrawerOpeningCalled = false
    addDrawerListener(object : SimpleDrawerListener() {
        override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
            super.onDrawerSlide(drawerView, slideOffset)
            if (!onDrawerOpeningCalled && slideOffset > 0f && !isDrawerOpen) {
                function(drawerLayout)
                onDrawerOpeningCalled = true
            }
        }

        override fun onDrawerStateChanged(newState: Int) {
            if (newState == STATE_IDLE) onDrawerOpeningCalled = false
        }
    })
}

用法:

drawer.onDrawerOpening {
    panelView.showingInPager(true) //Just my use case...
}
于 2021-12-17T20:29:14.513 回答
0

福克伍德的答案对我不起作用,但对 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
}
于 2017-07-06T19:47:15.513 回答