因此,当导航抽屉开始打开时,我有要隐藏的选项卡。当它完成打开时,我的代码会隐藏它们,但这不是我想要的。
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);
以下是我尝试过的:
- 将
onClickListener
设置为mDrawerLayout
。onClick
从不被调用 - 将
onTouchListener
设置为mDrawerLayout
。onTouch
从不被调用 - 对
ActionBarDrawerToggle
和DrawerLayout
类进行了研究。找不到类似onDrawerStartedOpening
的内容
已弃用:请参阅其他答案以获得更合适的解决方案
有两种可能的方法:
-
使用
onDrawerSlide(View drawerView, float slideOffset)
回调
slideOffset
从0变为1。1
表示完全打开,0
表示关闭。
一旦偏移量从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);
- 使用
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);
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.
}
});
工作非常完美。干杯
尝试覆盖DrawerLayout.DrawerListener 的方法
@Override
public void onDrawerStateChanged(int newState) {
if( newState == DrawerLayout.STATE_DRAGGING && isDrawerOpen() == false ) {
// this where Drawer start opening
}
}
最新解决方案:
正如其他人所建议的,目前的答案已经过时,建议使用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
}
}
});
当然,用任何能识别抽屉的东西(布局ID或其重力位置)代替GravityCompat.START
。
此外,如果你想检测抽屉何时开始关闭,你可以简单地做:
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
}
}
}
});
对于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()
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();
这是最好的方式。
我不明白为什么这里几乎每个人都建议使用结算,而这是在抽屉结算时调用的,所以在开始打开时没有?这个问题不是很清楚吗?
如何检测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...
}
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
}