2016-10-23 4 views
30

Я использую новый android.support.design.widget.BottomNavigationView из библиотеки поддержки. Как установить текущий код из кода? Я понял, что выбор меняется на первый элемент после поворота экрана. Конечно, это также помогло бы, если бы кто-нибудь мог мне сказать, как «сохранить» текущее состояние BottomNavigationView в функции и как его восстановить в onResume.Установить выбранный элемент в Android BottomNavigationView

Спасибо!

+1

Я только что посмотрел на источник, и у меня есть тот же вопрос .. Не похоже, что есть способ установить выделенный элемент, а 'BottomNavigationView' не выполняет никакой внутренней экономии состояния , Вероятно, ожидается, что это будет включено в будущее обновление. Дубликат (с дополнительной информацией) здесь: http://stackoverflow.com/questions/40236786/set-initially-selected-item-index-id-in-bottomnavigationview –

ответ

2

Кажется фиксироваться в SupportLibrary 25.1.0 :) Edit: Это, кажется, фиксируется, что состояние выбора сохраняется, при повороте экрана.

+1

Я только что обновил до 25.1.1. Проблема все еще существует. –

+0

Исправлено в 25.3.0 http://stackoverflow.com/a/43064105/969016 – Boy

4

Это, вероятно, будет добавлено в ближайшие обновления. Но тем временем, чтобы достичь этого, вы можете использовать отражение.

Создайте пользовательский вид, простирающийся от BottomNavigationView и получив доступ к некоторым его полям.

public class SelectableBottomNavigationView extends BottomNavigationView { 

    public SelectableBottomNavigationView(Context context) { 
     super(context); 
    } 

    public SelectableBottomNavigationView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public SelectableBottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    public void setSelected(int index) { 
     try { 
      Field f = BottomNavigationView.class.getDeclaredField("mMenuView"); 
      f.setAccessible(true); 
      BottomNavigationMenuView menuView = (BottomNavigationMenuView) f.get(this); 

      try { 
       Method method = menuView.getClass().getDeclaredMethod("activateNewButton", Integer.TYPE); 
       method.setAccessible(true); 
       method.invoke(menuView, index); 
      } catch (SecurityException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 
       e.printStackTrace(); 
      } 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } catch (NoSuchFieldException e) { 
      e.printStackTrace(); 
     } 
    } 

} 

И затем используйте его в своем файле макета xml.

<com.your.app.SelectableBottomNavigationView 
     android:id="@+id/bottom_navigation" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     app:itemBackground="@color/primary" 
     app:itemIconTint="@drawable/nav_item_color_state" 
     app:itemTextColor="@drawable/nav_item_color_state" 
     app:menu="@menu/bottom_navigation_menu"/> 
+0

Отражение - плохая идея! –

+0

Отличное решение, спасибо – diogojme

1

Я не хочу изменять ваш код. Если да, то я рекомендовал вам попробовать BottomNavigationViewEx.

Вам просто нужно заменить вызов метода setCurrentItem(index); и getCurrentItem().

Click here to view the image

0

отражение плохая идея.

Руководитель gist. Существует метод, который выполняет выбор, но и вызывает функцию обратного вызова:

@CallSuper 
    public void setSelectedItem(int position) { 
     if (position >= getMenu().size() || position < 0) return; 

     View menuItemView = getMenuItemView(position); 
     if (menuItemView == null) return; 
     MenuItemImpl itemData = ((MenuView.ItemView) menuItemView).getItemData(); 


     itemData.setChecked(true); 

     boolean previousHapticFeedbackEnabled = menuItemView.isHapticFeedbackEnabled(); 
     menuItemView.setSoundEffectsEnabled(false); 
     menuItemView.setHapticFeedbackEnabled(false); //avoid hearing click sounds, disable haptic and restore settings later of that view 
     menuItemView.performClick(); 
     menuItemView.setHapticFeedbackEnabled(previousHapticFeedbackEnabled); 
     menuItemView.setSoundEffectsEnabled(true); 


     mLastSelection = position; 

    } 
+0

Я использую 'callOnClick()' вместо 'performClick()', таким образом мне не нужно отключать звук, который не работал с 'performClick()' в любом случае. – arekolek

1

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

Menu bottomNavigationMenu = myBottomNavigationMenu.getMenu(); 
bottomNavigationMenu.performIdentifierAction(selected_menu_item_id, 0); 

performIdentifierAction принимает Menu идентификатор товара и флаг.

См. documentation для получения дополнительной информации.

+0

Это, похоже, выполняет действие, принадлежащее к элементу меню, но не вызывает выбор пункта меню. Я думал, что это то, чего хотел OP, но я не уверен. – LarsH

20

Я не уверен, является ли это полным ответом на этот вопрос, но моя проблема была очень похожа - мне пришлось обработать back нажатием кнопки и вывести пользователя на предыдущую вкладку, где он был. Так, может быть, мое решение будет полезно для кого-то:

private void updateNavigationBarState(int actionId){ 
    Menu menu = bottomNavigationView.getMenu(); 

    for (int i = 0, size = menu.size(); i < size; i++) { 
     MenuItem item = menu.getItem(i); 
     item.setChecked(item.getItemId() == actionId); 
    } 
} 

Пожалуйста, имейте в виду, что если пользователь нажмет другой вкладки навигации BottomNavigationView не очистит выбранный элемент, так что вам нужно вызвать этот метод в onNavigationItemSelected после обработка навигационных действий:

@Override 
public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
    switch (item.getItemId()) { 
     case R.id.some_id_1: 
      // process action 
      break; 
     case R.id.some_id_2: 
      // process action 
      break; 
     ... 
     default: 
      return false; 
    } 

    updateNavigationBarState(item.getItemId()); 

    return true; 
} 

Что касается сохранения состояния экземпляра я думаю, что вы могли бы играть с такими же action id зрения навигации и найти подходящее решение.

+0

Не меню 'menu = bottomNavigationView.getMenu();' возвращает копию меню, поэтому объект 'bottomNavigationView' не затрагивается? – dan

+0

@dan Согласно источнику, он возвращает атрибут класса mMenu, а не копию https: //android.googlesource.com/platform/frameworks/support/+/master/design/src/android/support/design/widget/BottomNavigationView.java? autodive = 0% 2F% 2F% 2F% 2F% 2F – Viacheslav

+1

http://stackoverflow.com/ a/43064105/969016 исправлено в 25.3.0 – Boy

3

Попробуйте мое решение от https://stackoverflow.com/a/40778162/2571249

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    bottomNavigationView.setOnNavigationItemSelectedListener(this); 
    Menu menu = bottomNavigationView.getMenu(); 
    this.onNavigationItemSelected(menu.findItem(R.id.action_favorites)); 
} 
0
private void setSelectedItem(int actionId) { 
    Menu menu = viewBottom.getMenu(); 
    for (int i = 0, size = menu.size(); i < size; i++) { 
     MenuItem menuItem = menu.getItem(i); 
     ((MenuItemImpl) menuItem).setExclusiveCheckable(false); 
     menuItem.setChecked(menuItem.getItemId() == actionId); 
     ((MenuItemImpl) menuItem).setExclusiveCheckable(true); 
    } 
} 

Единственный «минус» раствора с помощью MenuItemImpl, что «внутреннее» в библиотеке (хотя публика).

+0

теперь добавлено: http://stackoverflow.com/a/43064105/969016 – Boy

22

Чтобы программно нажать на пункт BottomNavigationBar вам нужно использовать:

View view = bottomNavigationView.findViewById(R.id.menu_action_item); 
view.performClick(); 

Это упорядочивает все элементы с их этикетками правильно.

+0

Спасибо, человек, я искал это для возрастов – temirbek

+0

Большое вам спасибо. Это решило проблему, которая меня очень раздражала. – helloimbarbara

+0

omg, спасибо soo много ... – user2129353

0

Я сделал ошибку в Google о том, что нет никакого надежного способа для выбора страницы на BottomNavigationView: https://code.google.com/p/android/issues/detail?id=233697

NavigationView по-видимому, имел такой же вопрос, который они неподвижный путем добавления нового setCheckedItem() метод.

3

Теперь можно так 25.3.0 версия для вызова setSelectedItemId() \ о/

47

От API 25.3.0 он был введен метод setSelectedItemId(int id) который позволяет вам пометить элемент, как выбран, как если бы он был использован.

Из документации:

Установите выбранный пункт меню ID. Это ведет себя так же, как постукивание по элементу. Пример

Код:

BottomNavigationView bottomNavigationView; 
bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottomNavigationView); 
bottomNavigationView.setOnNavigationItemSelectedListener(myNavigationItemListener); 
bottomNavigationView.setSelectedItemId(R.id.my_menu_item_id); 

ВАЖНО

Вы MUST уже добавили все пункты меню и установите Слушатель перед вызовом setSelectedItemId так, что BottomNavigationView может запустить соответствующий поведения кода. Если вы вызываете setSelectedItemId перед добавлением элементов меню и установкой слушателя, ничего не произойдет.

+1

Обратите внимание, что вызов 'setSelectedItemId()' does ** NOT ** работает внутри 'Activity.onCreate()', но работает внутри 'Activity.onResume()'. –

+4

Я просто протестировал его, и он ** РАБОТАЕТ ** внутри 'onCreate()' – Ricardo

+1

Это НЕ РАБОТАЕТ, он обновляет только вкладку, он не вызывает событие setOnNavigationItemSelectedListener – TjerkW

Смежные вопросы