Установить выбранный элемент в Android BottomNavigationView
Я использую новый android.support.design.widget.BottomNavigationView
из библиотеки поддержки.
Как установить текущий выбор из кода? Я понял, что выбор меняется обратно на первый пункт, после поворота экрана. Конечно, это также помогло бы, если бы кто-то мог сказать мне, как "сохранить" текущее состояние BottomNavigationView
на onPause
функция и как ее восстановить в onResume
.
спасибо!
14 ответов
из 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);
важно
вы должны уже добавили все элементы в меню и установите прослушиватель перед вызовом setSelectedItemId так что BottomNavigationView может запускать поведение соответствующего кода. Если вы вызываете setSelectedItemId перед добавлением пунктов меню и установкой прослушивателя, ничего не произойдет.
чтобы программно щелкнуть элемент BottomNavigationBar, вам нужно использовать:
View view = bottomNavigationView.findViewById(R.id.menu_action_item);
view.performClick();
это упорядочивает все элементы с их метками правильно.
для тех, кто все еще использует SupportLibrary
Я не уверен, что это полный ответ на этот вопрос, но моя проблема была очень похожа - мне пришлось обработать 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
навигации посмотреть и найти подходящее решение.
это, вероятно, будет добавлено в ближайшие обновления. Но в то же время, для этого вы можете использовать отражение.
создайте пользовательское представление, расширяющееся из 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"/>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bottomNavigationView.setOnNavigationItemSelectedListener(this);
Menu menu = bottomNavigationView.getMenu();
this.onNavigationItemSelected(menu.findItem(R.id.action_favorites));
}
Я вы не хотите изменять свой код. Если это так, я рекомендовал вам попробовать BottomNavigationViewEx。
вам просто нужно заменить вызов метода setCurrentItem(index);
и getCurrentItem()
。
кажется, исправлено в SupportLibrary 25.1.0 :) Edit: кажется, исправлено, что состояние выбора сохраняется при вращении экрана.
выше API 25 вы можете использовать setSelectedItemId(menu_item_id) но под API 25 вы должны сделать по-другому, меню пользователя, чтобы получить дескриптор, а затем setChecked для проверки конкретного элемента
просто добавление другого способа выполнения выбора программно-это, вероятно, то, что было намерение в первую очередь, или, может быть, это было добавлено позже.
Menu bottomNavigationMenu = myBottomNavigationMenu.getMenu();
bottomNavigationMenu.performIdentifierAction(selected_menu_item_id, 0);
на performIdentifierAction
принимает Menu
идентификатор элемента и флаг.
посмотреть документация для получения дополнительной информации.
добавить android:enabled="true"
к пунктам BottomNavigationMenu.
и затем установить bottomNavigationView.setOnNavigationItemSelectedListener(mListener)
и
установить его как выбрать bottomNavigationView.selectedItemId = R.id.your_menu_id
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
, который является "внутренним" для библиотеки (хотя и общедоступным).
Я сделал ошибку в Google о том, что нет надежного способа выбрать страницу на BottomNavigationView:https://code.google.com/p/android/issues/detail?id=233697
NavigationView, по-видимому, имел аналогичную проблему, которую они исправили, добавив новый метод setCheckedItem ().
отражение-плохая идея.
этот суть. Существует метод, который выполняет выбор, но также вызывает обратный вызов:
@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;
}