Скрыть ActionBar MenuItems, когда навигационный ящик слайдов для любой суммы
Я пытаюсь реализовать навигационный ящик, который скрывает элементы меню в ActionBar всякий раз, когда ящик открывается.
Я следую документации Google, однако их код не вызывает ожидаемого поведения.
http://developer.android.com/training/implementing-navigation/nav-drawer.html
Используя этот код, элементы меню скрыты, когда ящик полностью открывается и отображается, когда ящик полностью закрыт.
Однако приложение Gmail ведет себя по-разному. Элементы меню скрываются, как только ящик открывается на любую сумму. Это поведение, которое я хочу. Кто-нибудь знает, как добиться этого?
Спасибо!
Ответы
Ответ 1
Вы пробовали это:
- Используйте
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
- это поле класса.
Ответ 2
Если вы хотите переопределить панель действий, как только ящик войдет в экранную панель и панель действий восстановления, ящик момента больше не отображается (как именно работает Gmail по состоянию на 20 марта 2014 года), вы можете использовать следующий код:
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
.
Ответ 3
Я бы согласился с 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);
}
Ответ 4
У меня есть лучшее решение для этого вопроса:
@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);
}
Ответ 5
Если вы хотите скрыть все пункты меню, просто используйте:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
return showActionBarMenu; // boolean value, set it in drawer listeners as class variable
}
Затем вам не нужно видеть каждый элемент меню.
Ответ 6
Я взял ответ от @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);
}
Несколько заметок:
- Вышеприведенная реализация предполагает, что представление, связанное с NavigationDrawer, имеет свой
layout_gravity
, установленный в start
в XML.
- Не связан с вопросом OP, но раздражает: похоже, есть какая-то ошибка, из-за которой ящик застревает на этом пути. Если вы наблюдаете это поведение, вот решение: Ошибка Android Drawer Drawer с использованием примера
Ответ 7
У меня есть другой код, но то же самое решение:
@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();
}
}