Подтвердить что ты не робот

Скрыть ActionBar MenuItems, когда навигационный ящик слайдов для любой суммы

Я пытаюсь реализовать навигационный ящик, который скрывает элементы меню в ActionBar всякий раз, когда ящик открывается.

Я следую документации Google, однако их код не вызывает ожидаемого поведения.

http://developer.android.com/training/implementing-navigation/nav-drawer.html

Используя этот код, элементы меню скрыты, когда ящик полностью открывается и отображается, когда ящик полностью закрыт.

Однако приложение Gmail ведет себя по-разному. Элементы меню скрываются, как только ящик открывается на любую сумму. Это поведение, которое я хочу. Кто-нибудь знает, как добиться этого?

Спасибо!

4b9b3361

Ответ 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();
    }
}