webentwicklung-frage-antwort-db.com.de

Legen Sie das ausgewählte Element in Android BottomNavigationView fest

Ich verwende den neuen Android.support.design.widget.BottomNavigationView aus der Support-Bibliothek . Wie kann ich die aktuelle Auswahl anhand des Codes festlegen? Ich stellte fest, dass die Auswahl nach dem Drehen des Bildschirms wieder auf den ersten Punkt geändert wurde. Natürlich würde es auch helfen, wenn mir jemand sagen könnte, wie man den aktuellen Zustand der BottomNavigationView in der onPause-Funktion "speichert" und wie man ihn in onResume wiederherstellt.

Vielen Dank!

64
Michael

Scheint in SupportLibrary 25.1.0 behoben zu sein:) Edit: Es scheint fest zu sein, dass der Status der Auswahl beim Drehen des Bildschirms gespeichert wird.

2
Michael

Ab API 25.3.0 wurde die Methode setSelectedItemId(int id) eingeführt, mit der Sie ein Element als ausgewählt markieren, als wäre es angetippt worden.

Aus docs:

Stellen Sie die ausgewählte Menüelement-ID ein. Dies entspricht dem Tippen auf einen Artikel.

Code-Beispiel:

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

WICHTIG

Sie MÜSSEN bereits alle Elemente zum Menü hinzugefügt und den Listener vor dem Aufruf von setSelectedItemId festgelegt haben, damit BottomNavigationView das Verhalten des entsprechenden Codes ausführen kann. Wenn Sie setSelectedItemId aufrufen, bevor Sie die Menüelemente hinzufügen und den Listener festlegen, geschieht nichts.

99
Ricardo

Um programmgesteuert auf das Element BottomNavigationBar zu klicken, benötigen Sie:

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

Dies ordnet alle Artikel mit ihren Etiketten korrekt an.

43
karenms

Für diejenigen, die noch SupportLibrary <25.3.0 verwenden

Ich bin nicht sicher, ob dies eine vollständige Antwort auf diese Frage ist, aber mein Problem war sehr ähnlich - ich musste back drücken und den Benutzer zum vorherigen Tab bringen, wo er war. Vielleicht ist meine Lösung für jemanden nützlich:

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);
    }
}

Bitte beachten Sie, dass BottomNavigationView das aktuell ausgewählte Element nicht löscht, wenn der Benutzer auf eine andere Navigationsregisterkarte klickt. Daher müssen Sie diese Methode nach der Verarbeitung der Navigationsaktion in Ihrer onNavigationItemSelected aufrufen:

@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;
}

In Bezug auf das Speichern des Instanzzustands denke ich, Sie könnten mit demselben action id der Navigationsansicht spielen und eine geeignete Lösung finden.

33
Viacheslav

Seit der Version 25.3.0 ist es jetzt möglich, setSelectedItemId()\o/aufzurufen.

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

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

Dies wird wahrscheinlich in den kommenden Updates hinzugefügt. Um dies zu erreichen, können Sie in der Zwischenzeit Reflektion verwenden.

Erstellen Sie eine benutzerdefinierte Ansicht, die sich von BottomNavigationView aus erstreckt, und greifen Sie auf einige ihrer Felder zu.

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();
        }
    }

}

Und dann verwenden Sie es in Ihrer XML-Layoutdatei.

<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

Fügen Sie Android:enabled="true" zu den Elementen des BottomNavigationMenu hinzu.

Stellen Sie dann bottomNavigationView.setOnNavigationItemSelectedListener(mListener) und Ein, indem Sie bottomNavigationView.selectedItemId = R.id.your_menu_id auswählen.

2

Über API 25 können Sie setSelectedItemId (menu_item_id) Verwenden. Unter API 25 müssen Sie jedoch ein anderes Benutzermenü verwenden, um das Handle abzurufen, und setChecked auf Checked Specific Item

2
mhheydarchi

Sie möchten Ihren Code nicht ändern ... Wenn ja, empfehle ich Ihnen, BottomNavigationViewEx 。 zu versuchen.

Sie brauchen nur zu ersetzen, rufen Sie eine Methode setCurrentItem(index); und getCurrentItem() call auf.

Click here to view the image

2
ittianyu

Einfach eine andere Möglichkeit hinzufügen, um eine Auswahl programmatisch durchzuführen - dies war wahrscheinlich ursprünglich die Absicht oder vielleicht wurde diese später hinzugefügt.

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

Die Variable performIdentifierAction nimmt eine Menu-Element-ID und ein Flag an.

Weitere Informationen finden Sie in der Dokumentation documentation .

1
Darwind

Sie können die performClick-Methode ausprobieren:

View view = bottomNavigationView.findViewById(R.id.YOUR_ACTION);
view.performClick();
1
ismail alaoui
bottomNavigationView.setSelectedItemId(R.id.action_item1);

dabei ist action_item1 die Menüelement-ID.

1
Ashwini

WENN SIE FRAGMENTARGUMENTE DYNAMISCH PASSIEREN MÜSSEN, MACHEN SIE DAS

Hier gibt es viele (meist wiederholte oder veraltete) Antworten, aber keine von ihnen behandelt ein sehr häufiges Problem: Dynamische Übergabe verschiedener Argumente an das Fragment, das in eine Registerkarte geladen wurde .

Sie können mit setSelectedItemId(R.id.second_tab) keine unterschiedlichen Argumente dynamisch an das geladene Fragment übergeben, wodurch das statische OnNavigationItemSelectedListener aufgerufen wird. Um diese Einschränkung zu überwinden, habe ich dies in meinem MainActivity getan, das die folgenden Registerkarten enthält:

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()
}

Die Methode ArticleFragment.newInstance() wird wie gewohnt implementiert:

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
        }
    }

}
0

Ich habe einen Fehler mit Google in Bezug auf die Tatsache gemacht, dass es keine zuverlässige Möglichkeit gibt, die Seite in einer BottomNavigationView auszuwählen: https://code.google.com/p/Android/issues/detail?id=233697

In NavigationView gab es anscheinend ein ähnliches Problem, das durch das Hinzufügen einer neuen Methode setCheckedItem () behoben wurde. 

0
Johan Paul
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);
    }
}

Das einzige "Minus" der Lösung ist MenuItemImpl, das 'intern' für die Bibliothek ist (obwohl es öffentlich ist).

0
Alexey