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

Установите выделенный элемент в Android BottomNavigationView

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

Спасибо!

4b9b3361

Ответ 1

Кажется, исправлено в SupportLibrary 25.1.0:) Изменить: Кажется, исправлено, что состояние выбора сохраняется при вращении экрана.

Ответ 2

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

Из документов:

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

Пример кода:

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

ВАЖНЫЙ

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

Ответ 3

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

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

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

Ответ 4

Для тех, кто все еще использует SupportLibrary <25.3.0

Я не уверен, является ли это полным ответом на этот вопрос, но моя проблема была очень похожа - мне пришлось обработать нажатие кнопки 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 другую вкладку навигации, 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 в виде навигации и найти подходящее решение.

Ответ 5

bottomNavigationView.setSelectedItemId(R.id.action_item1);

где action_item1 - идентификатор пункта меню.

Ответ 6

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

   bottomNavigationView.setOnNavigationItemSelectedListener(this);
   Menu menu = bottomNavigationView.getMenu();
   this.onNavigationItemSelected(menu.findItem(R.id.action_favorites));
}

Ответ 7

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

Ответ 8

Добавьте android:enabled="true" в элементы BottomNavigationMenu.

А затем установите bottomNavigationView.setOnNavigationItemSelectedListener(mListener) и установите его как выбранный, выполнив bottomNavigationView.selectedItemId = R.id.your_menu_id

Ответ 9

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

Создайте пользовательский вид, простирающийся от 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"/>

Ответ 10

Выше API 25 вы можете использовать setSelectedItemId (menu_item_id), но в API 25 вы должны сделать иначе, пользовательское меню, чтобы получить дескриптор, а затем установитьChecked на Проверяемый конкретный элемент

Ответ 11

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

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

Click here to view the image

Ответ 12

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

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

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

Дополнительную информацию см. в документации .

Ответ 13

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

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

Ответ 14

Вы можете попробовать метод executeClick:

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

Ответ 15

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, который является "внутренним" для библиотеки (хотя и общедоступным).

Ответ 16

Просто поместите это в свой XML файл, где у вас есть bottomnavigationView.

'<android.support.design.widget.BottomNavigationView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:itemIconSize="15dp"/>'

Ответ 17

ЕСЛИ ВАМ НУЖНО ДИНАМИЧЕСКИ ПРОЙТИ ФРАГМЕНТНЫЕ АРГУМЕНТЫ, ДЕЛАЙТЕ ЭТО

Здесь есть множество (в основном повторяющихся или устаревших) ответов, но ни один из них не удовлетворяет очень распространенной необходимости: динамически передавать различные аргументы фрагменту, загруженному во вкладку.

Вы не можете динамически передавать различные аргументы загруженному фрагменту, используя setSelectedItemId(R.id.second_tab), который в итоге вызывает статический OnNavigationItemSelectedListener. Чтобы преодолеть это ограничение, я сделал это в моем MainActivity, который содержит вкладки:

fun loadArticleTab(articleId: String) {
    bottomNavigationView.menu.findItem(R.id.tab_article).isChecked = true // use setChecked() in Java
    supportFragmentManager
        .beginTransaction()
        .replace(R.id.main_fragment_container, ArticleFragment.newInstance(articleId))
        .commit()
}

Метод ArticleFragment.newInstance() реализован как обычно:

private const val ARG_ARTICLE_ID = "ARG_ARTICLE_ID"

class ArticleFragment : Fragment() {

    companion object {
        /**
         * @return An [ArticleFragment] that shows the article with the given ID.
         */
        fun newInstance(articleId: String): ArticleFragment {
            val args = Bundle()
            args.putString(ARG_ARTICLE_ID, day)
            val fragment = ArticleFragment()
            fragment.arguments = args
            return fragment
        }
    }

}

Ответ 18

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

Направляйтесь в 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;

    }