Соединить фрагменты с нижней навигацией [duplicate]

Каждая переменная в Java является ссылкой. Поэтому, когда вы делаете

SomeClass s2 = s1;

, вы просто указываете s2 на тот же объект, что и s1. Фактически вы назначаете значение ссылки s1 (которое указывает на экземпляр SomeClass) на s2. Если вы измените s1, будет также изменен s2 (потому что он указывает на тот же объект).

Существует исключение, примитивные типы: int, double, float, boolean, char, byte, short, long. Они хранятся по значению. Поэтому при использовании = вы присваиваете значение только, но не можете указывать на один и тот же объект (потому что это не ссылки). Это означает, что

int b = a;

устанавливает значение b в значение a. Если вы измените a, b не изменится.

В конце дня все назначается по значению, это всего лишь значение ссылки, а не значение объекта (с исключение примитивных типов, как указано выше).

Итак, в вашем случае, если вы хотите сделать копию s1, вы можете сделать это следующим образом:

SomeClass s1 = new SomeClass("first");
SomeClass s2 = new SomeClass(s1.getText());

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

class SomeClass {
  private String text;
  // all your fields and methods go here

  public SomeClass(SomeClass copyInstance) {
    this.text = new String(copyInstance.text);
  }
}

С помощью этого вы можете легко скопировать объект:

SomeClass s2 = new SomeClass(s1);
43
задан Bugs Happen 20 April 2017 в 12:57
поделиться

14 ответов

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

2
ответ дан Michael 16 August 2018 в 14:30
поделиться
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
ответ дан bibi 16 August 2018 в 14:30
поделиться

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

5
ответ дан Boy 16 August 2018 в 14:30
поделиться

Попробуйте мое решение из 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));
}
3
ответ дан Community 16 August 2018 в 14:30
поделиться

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

Создайте пользовательский вид, простирающийся от 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"/>
3
ответ дан cpienovi 16 August 2018 в 14:30
поделиться

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

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

performIdentifierAction принимает Menu id и флаг.

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

1
ответ дан Darwind 16 August 2018 в 14:30
поделиться
  • 1
    Это, похоже, выполняет действие, принадлежащее элементу меню, но не вызывает выбор пункта меню. Я думал, что это то, чего хотел OP, но я не уверен. – LarsH 8 December 2016 в 06:19

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

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

Click here to view the image [/g1]

2
ответ дан ittianyu 16 August 2018 в 14:30
поделиться

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

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

0
ответ дан Johan Paul 16 August 2018 в 14:30
поделиться

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

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

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

24
ответ дан karenms 16 August 2018 в 14:30
поделиться
  • 1
    Спасибо, человек, я давно искал это – temirbek 23 March 2017 в 14:03
  • 2
    Огромное спасибо. Это решило проблему, которая меня очень раздражала. – helloimbarbara 11 April 2017 в 15:37
  • 3
    omg, большое вам спасибо ... – user2129353 20 April 2017 в 18:53
  • 4
    @karenms идеальный ответ. Отличная работа – Mitesh Jain 8 June 2017 в 09:16
  • 5
    Это взломать проблему. У вас есть методы из самой библиотеки, которые позволят вам выполнять то, что вам нужно. Если вы не можете это сделать, это потому, что вы делаете это неправильно – Ricardo 23 February 2018 в 18:20

Выше API 25 вы можете использовать setSelectedItemId (menu_item_id), но в соответствии с API 25 вы должны сделать по-другому, пользовательское меню, чтобы получить дескриптор, а затем setChecked to Checked specific item

2
ответ дан mhheydarchi 16 August 2018 в 14:30
поделиться

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

Направьте этот 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;

    }
-1
ответ дан Nikola Despotoski 16 August 2018 в 14:30
поделиться
  • 1
    Я использую callOnClick() вместо performClick(), поэтому мне не нужно отключать звук, который в любом случае не работает с performClick(). – arekolek 14 March 2017 в 16:08

Из 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 перед добавлением пунктов меню и установкой слушателя, ничего не произойдет.

67
ответ дан Ricardo 16 August 2018 в 14:30
поделиться
  • 1
    Обратите внимание, что при вызове setSelectedItemId() функция NOT работает внутри Activity.onCreate(), но работает внутри Activity.onResume(). – Andy H. 4 May 2017 в 21:07
  • 2
    Я просто проверил его, и он РАБОТАЕТ внутри onCreate() – Ricardo 5 May 2017 в 08:24
  • 3
    Это НЕ РАБОТАЕТ, оно обновляет только вкладку, она не вызывает событие setOnNavigationItemSelectedListener – TjerkW 27 September 2017 в 09:24
  • 4
    Если вы не определили поведение в onTabSelected, очевидно, что ничего не сделаете. Прочтите документы - & gt; Установите выбранный идентификатор элемента меню. Это ведет себя так же, как постукивание по элементу. Это от разработчиков Android – Ricardo 27 September 2017 в 09:57
  • 5
    В моем случае это не работало, потому что я программировал меню навигации. Во время строительства клик не работал. После того, как все элементы добавлены в меню, вызывается функция setSelectedItemId (). – Pedro Romão 27 February 2018 в 11:58

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

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

0
ответ дан Rumaan Khalander 16 August 2018 в 14:30
поделиться

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

24
ответ дан Viacheslav 16 August 2018 в 14:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: