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!
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.
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.
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.
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.
Seit der Version 25.3.0 ist es jetzt möglich, setSelectedItemId()
\o/aufzurufen.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bottomNavigationView.setOnNavigationItemSelectedListener(this);
Menu menu = bottomNavigationView.getMenu();
this.onNavigationItemSelected(menu.findItem(R.id.action_favorites));
}
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"/>
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.
Ü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
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.
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 .
Sie können die performClick-Methode ausprobieren:
View view = bottomNavigationView.findViewById(R.id.YOUR_ACTION);
view.performClick();
bottomNavigationView.setSelectedItemId(R.id.action_item1);
dabei ist action_item1
die Menüelement-ID.
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
}
}
}
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.
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).