我正在尝试实现一个导航抽屉,只要打开抽屉,它就会隐藏ActionBar中的菜单项。
我正在关注谷歌的文档,但他们的代码不会产生预期的行为。
http://developer.android.com/training/implementing-navigation/nav-drawer.html
使用此代码,当抽屉完全打开时,菜单项将被隐藏,并在抽屉完全关闭时显示。
但是,Gmail应用的行为有所不同。一旦抽屉以任何数量打开,菜单项就会被隐藏。这是我想要的行为。有谁知道如何实现这个目标?
谢谢!
答案 0 :(得分:47)
你试过这个:
invalidateOptionsMenu()
。对onPrepareOptionsMenu(Menu menu)
中的每个菜单项进行迭代并隐藏它。
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = shouldGoInvisible;
hideMenuItems(menu, !drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
private void hideMenuItems(Menu menu, boolean visible)
{
for(int i = 0; i < menu.size(); i++){
menu.getItem(i).setVisible(visible);
}
}
检测导航抽屉滑落的程度:
mDrawerLayout.setDrawerListener(new DrawerListener(){
float mPreviousOffset = 0f;
@Override
public void onDrawerClosed(View arg0) {
super.onDrawerClosed(arg0);
shouldGoInvisible = false;
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
@Override
public void onDrawerOpened(View arg0) {
super.onDrawerOpened(arg0);
shouldGoInvisible = true;
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
@Override
public void onDrawerSlide(View arg0, float slideOffset) {
super.onDrawerSlide(arg0, slideOffset);
if(slideOffset > mPreviousOffset && !shouldGoInvisible){
shouldGoInvisible = true;
invalidateOptionsMenu();
}else if(mPreviousOffset > slideOffset && slideOffset < 0.5f && shouldGoInvisible){
shouldGoInvisible = false;
invalidateOptionsMenu();
}
mPreviousOffset = slideOffset;
}
@Override
public void onDrawerStateChanged(int arg0) {
// or use states of the drawer to hide/show the items
}});
注意:shouldGoInvisible
是类字段。
答案 1 :(得分:5)
如果您想在抽屉进入屏幕后立即覆盖操作栏并恢复操作栏,那么当前抽屉不再可见(截至2014年3月20日Gmail的行为方式),您可以使用以下代码:
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerStateChanged(int newState) {
super.onDrawerStateChanged(newState);
boolean isOpened = mDrawerLayout.isDrawerOpen(mDrawerList);
boolean isVisible = mDrawerLayout.isDrawerVisible(mDrawerList);
if (!isOpened && !isVisible) {
if (newState == DrawerLayout.STATE_IDLE) {
// drawer just hid completely
restoreActionBar();
} else {
// } else if (newState == DrawerLayout.STATE_SETTLING) {
// drawer just entered screen
overrideActionBar();
}
}
}
private void restoreActionBar() {
getSupportActionBar().setTitle(mTitle);
supportInvalidateOptionsMenu();
}
private void overrideActionBar() {
getSupportActionBar().setTitle(mDrawerTitle);
supportInvalidateOptionsMenu();
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
根据您的需要修改restoreActionBar()
和overrideActionBar()
方法。
无需区分滑动和主页按钮,也无需测量滑动长度。
如果您不想引用抽屉列表视图,请改为使用以下代码:
boolean isOpened = mDrawerLayout.isDrawerOpen(GravityCompat.START);
boolean isVisible = mDrawerLayout.isDrawerVisible(GravityCompat.START);
您可能希望使用GravityCompat.END
,具体取决于您在XML布局中指定的内容。
以上示例不会隐藏与导航抽屉下方内容相关的操作栏项。要在抽屉可见时执行此操作或显示不同的图标集,您必须手动跟踪抽屉是打开还是关闭。
除上述代码外,还声明private boolean mDrawerVisible = false
具有正确的保存/恢复状态处理。
然后修改mDrawerToggle
内部方法,如下所示:
private void restoreActionBar() {
getSupportActionBar().setTitle(mTitle);
mDrawerVisible = false;
supportInvalidateOptionsMenu();
}
private void overrideActionBar() {
getSupportActionBar().setTitle(mDrawerTitle);
mDrawerVisible = true;
supportInvalidateOptionsMenu();
}
最后在onCreateOptionsMenu
中填充不同的菜单资源或onPrepareOptionsMenu
根据mDrawerVisible
的值显示/隐藏不同的操作。
答案 2 :(得分:2)
我半数同意Nikola,但只有在抽屉状态出现时更新图标就足够了
创建一个全局变量来跟踪抽屉状态:
private int mDrawerState;
设置一个新的DrawerListener:
mDrawerLayout.setDrawerListener(new DrawerListener() {
@Override
public void onDrawerStateChanged(int state) {
mDrawerState = state;
invalidateOptionsMenu();
}
@Override
public void onDrawerSlide(View view, float slide) {
// TODO Auto-generated method stub
}
@Override
public void onDrawerOpened(View view) {
// TODO Auto-generated method stub
}
@Override
public void onDrawerClosed(View view) {
// TODO Auto-generated method stub
}
});
更新菜单可见性:
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawer);
for(int i=0;i<menu.size();i++){
// If the drawer is moving / settling or open do not draw the icons
menu.getItem(i).setVisible(mDrawerState!=DrawerLayout.STATE_DRAGGING &&
mDrawerState!=DrawerLayout.STATE_SETTLING && !drawerOpen);
}
答案 3 :(得分:1)
我对这个问题有更好的解决方案:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (navigationDrawerFragment.isDrawerOpen()) {
menu.clear();
}
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!navigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
showLocalContextActionBar();
return false;
}
return super.onCreateOptionsMenu(menu);
}
答案 4 :(得分:0)
如果要隐藏所有菜单项,只需使用:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
return showActionBarMenu; // boolean value, set it in drawer listeners as class variable
}
然后您不需要看到每个菜单项。
答案 5 :(得分:0)
我接受了@Laurence Dawson的回答并简化了一下。此解决方案不需要使用任何类成员。
在onCreate()
期间执行此代码:
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(View view, float v) {
invalidateOptionsMenu();
}
@Override
public void onDrawerClosed(View view) {
invalidateOptionsMenu();
}
@Override
public void onDrawerOpened(View view) {}
@Override
public void onDrawerStateChanged(int state) {}
});
并覆盖此方法:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
boolean actionsVisibility = !drawerLayout.isDrawerVisible(Gravity.START);
for(int i=0;i<menu.size();i++){
menu.getItem(i).setVisible(actionsVisibility);
}
return super.onPrepareOptionsMenu(menu);
}
很少注意到:
layout_gravity
设置为start
。答案 6 :(得分:0)
我有不同的代码但是同样的解决方案:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
hideMenuItems(menu, !mShouldGoInvisible);
return super.onCreateOptionsMenu(menu);
}
private void hideMenuItems(Menu menu, boolean visible){
for(int i = 0; i < menu.size(); i++){
menu.getItem(i).setVisible(visible);
}
}
和
@Override
public void onNavigationDrawerListener(boolean opened, int position) {
if (opened){
mShouldGoInvisible = true;
invalidateOptionsMenu();
} else {
mShouldGoInvisible = false;
invalidateOptionsMenu();
}
}