Android BottomNavigationView'da seçili öğeyi ayarla


123

android.support.design.widget.BottomNavigationViewDestek kitaplığındaki yeniyi kullanıyorum . Geçerli seçimi koddan nasıl ayarlayabilirim? Ekranı döndürdükten sonra seçimin ilk öğeye geri döndüğünü fark ettim. Elbette, eğer biri bana söylerse BottomNavigationView, onPauseişlevin mevcut durumunu nasıl "kaydedeceğimi" ve onu nasıl geri yükleyeceğimi de yardımcı olacaktır onResume.

Teşekkürler!


1
Kaynağa yeni bir göz attım ve aynı sorum var .. Seçilen öğeyi ayarlamak için bir yöntem yok gibi görünmüyor ve BottomNavigationViewherhangi bir dahili durum kaydetme yapmıyor. Muhtemelen bunun gelecekteki bir güncellemeye dahil edilmesini bekliyoruz. Kopyalayın (biraz daha fazla bilgi ile) burada: stackoverflow.com/questions/40236786/…
Tim Malseed

Yanıtlar:


171

API 25.3.0'dan, setSelectedItemId(int id)bir öğeyi tıklanmış gibi seçilmiş olarak işaretlemenizi sağlayan yöntem tanıtıldı .

Dokümanlardan:

Seçili menü öğesi kimliğini ayarlayın. Bu, bir öğeye dokunmakla aynı şekilde davranır.

Kod örneği:

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

ÖNEMLİ

Tüm öğeleri menüye zaten eklemiş olmanız (bunu programlı olarak yapmanız durumunda) ve setSelectedItemId'i çağırmadan önce Dinleyiciyi ayarlamış olmanız GEREKİR (Bu yöntemi çağırdığınızda dinleyicinizdeki kodun çalışmasını istediğinize inanıyorum). Menü öğelerini eklemeden ve dinleyiciyi ayarlamadan önce setSelectedItemId öğesini çağırırsanız hiçbir şey olmaz.


3
Bu ÇALIŞMAZ, yalnızca sekmenin kendisini günceller, bir setOnNavigationItemSelectedListener olayını tetiklemez
TjerkW

1
Davranışı onTabSelectedaçıkça tanımlamadıysanız, hiçbir şey yapmayacaktır. Belgeleri okuyun -> Seçili menü öğesi kimliğini ayarlayın. Bu, bir öğeye dokunmakla aynı şekilde davranır. Android Geliştiricilerinden
Ricardo

1
Hata ayıklamanızı ve yanlış yaptığınız şeyi gözden geçirmenizi şiddetle tavsiye ederim. Zaten üç BottomNavigationView Uygulamasını uyguladım ve bu yöntemle hiç sorun yaşamadım.
Ricardo

@Ricardo Bunu parçama eklediğimde, o parçaya girerken uygulama takıldı
Subin Babu

1
Benim durumumda çalışmıyordu çünkü programlı olarak navigasyon menüsü oluşturuyordum. İnşaat sırasında tıklama işe yaramadı. Menüye tüm öğeler eklendikten sonra setSelectedItemId () çağrısı çalıştı.
Pedro Romão

53

BottomNavigationBar öğesine programlı olarak tıklamak için kullanmanız gereken:

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

Bu, tüm öğeleri etiketleriyle doğru şekilde düzenler.


4
Bu, sorunla ilgili bir hack'tir. Kütüphaneden, ihtiyacınız olanı gerçekleştirmenize izin verecek yöntemlere sahipsiniz.
Ricardo

47

Hala SupportLibrary <25.3.0 kullananlar için

Bunun bu soruya tam bir yanıt olup olmadığından emin değilim, ancak benim sorunum çok benzerdi - backdüğmeye basmayı işlemek ve kullanıcıyı bulunduğu önceki sekmeye getirmek zorunda kaldım . Yani, belki benim çözümüm birileri için yararlı olabilir:

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

Lütfen, kullanıcı diğer gezinme sekmesine BottomNavigationViewbasarsa o anda seçili öğeyi temizlemeyeceğini, bu nedenle onNavigationItemSelectedgezinme eylemini işledikten sonra bu yöntemi çağırmanız gerektiğini unutmayın :

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

Örnek durumunun kaydedilmesiyle ilgili olarak, aynı action idnavigasyon görünümü ile oynayıp uygun çözümü bulabileceğinizi düşünüyorum .


Nesnenin etkilenmemesi Menu menu = bottomNavigationView.getMenu();için menünün bir kopyasını döndürmüyor bottomNavigationViewmu?
最 白 目


6
Diğer öğelerin işaretini kaldırmanıza gerek yok, en azından 26.1.0 / 27.1.0
Jemshit Iskenderov

işaretini kaldırmayın, onları vurgulayacaktır
djdance

19
bottomNavigationView.setSelectedItemId(R.id.action_item1);

action_item1menü öğesi kimliği nerede .


8
@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 sürümünden beri setSelectedItemId()\ o / çağrısı yapmak artık mümkün.


5

android:enabled="true"BottomNavigationMenu Öğelerine Ekle .

Ve sonra bottomNavigationView.setOnNavigationItemSelectedListener(mListener)bunu yaparak seçili olarak ayarlayın ve ayarlayınbottomNavigationView.selectedItemId = R.id.your_menu_id


3

Bu muhtemelen gelecek güncellemelerde eklenecektir. Ancak bu arada, bunu başarmak için yansımayı kullanabilirsiniz.

BottomNavigationView'dan genişleyen özel bir görünüm oluşturun ve bazı alanlarına erişin.

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

}

Ve sonra xml düzen dosyanızda kullanın.

<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
Düşünmek kötü bir fikirdir!
Filipe Brito

performClick bu durumda yansımadan daha iyidir, imho.
Lassi Kinnunen

3

Sadece bir seçimi programlı olarak gerçekleştirmenin başka bir yolunu eklemek - muhtemelen ilk başta niyet buydu veya belki bu daha sonra eklenmiştir.

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

performIdentifierActionBir sürer Menuöğe kimliği ve bir bayrak.

Daha fazla bilgi için belgelere bakın .


Bu, menü öğesine ait eylemi gerçekleştiriyor gibi görünüyor, ancak menü öğesinin seçili görünmesine neden olmuyor. İkincisinin OP'nin istediği şey olduğunu sanıyordum ama olumlu değilim.
LarsH

3

SupportLibrary 25.1.0'da düzeltilmiş görünüyor :) Düzenle: Ekran döndürülürken seçim durumunun kaydedildiği düzeltildi.


1
25.1.1'e yeni güncelledim. Sorun hala mevcut.
Xi Wei

3

API 25'in yukarısında setSelectedItemId (menu_item_id) kullanabilirsiniz, ancak API 25 altında farklı bir şekilde yapmanız gerekir, kullanıcı Menüsünü işlemek için ve ardından Kontrol edilen belirli bir öğe olarak ayarlayın


3

Seçili alt gezinme menü öğesini menü kimliğine göre ayarlamak için bunu kullanın

MenuItem item = mBottomNavView.getMenu().findItem(menu_id);
item.setChecked(true);


2

kullanım

        bottomNavigationView.getMenu().getItem(0).setChecked(true);


1

PerformClick yöntemini deneyebilirsiniz:

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

0

Düşünmek kötü bir fikir.

Bu öze gidin . Seçimi gerçekleştiren ancak aynı zamanda geri aramayı da başlatan bir yöntem vardır:

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

    }

Bunun callOnClick()yerine kullanıyorum performClick(), bu şekilde performClick()zaten çalışmayan sesi devre dışı bırakmam gerekmiyor .
arekolek

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

Çözümün tek 'eksi', MenuItemImplkütüphaneye 'dahili' olan (herkese açık olsa da) kullanıyor.


0

DİNAMİK OLARAK GEÇMENİZ GEREKİYORSA BUNU YAPIN

Burada pek çok (çoğunlukla tekrarlanan veya geçerliliğini yitirmiş) yanıtlar vardır, ancak bunların hiçbiri çok yaygın bir ihtiyacı karşılamamaktadır: farklı argümanları bir sekmeye yüklenen Parçaya dinamik olarak iletmek .

Kullanarak yüklenen Parçaya dinamik olarak farklı argümanlar iletemezsiniz setSelectedItemId(R.id.second_tab), bu da statik çağrıyı sonlandırır OnNavigationItemSelectedListener. Bu sınırlamanın üstesinden gelmek için MainActivity, sekmeleri içeren bende bunu yaptım :

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()Yöntem her zamanki gibi uygulanır:

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

Umarım bu yardımcı olur

//Setting default selected menu item and fragment
        bottomNavigationView.setSelectedItemId(R.id.action_home);
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.fragment_container, new HomeFragment()).commit();

Karşılık gelen alt gezinme menü öğesi ile aynı anda yüklenen varsayılan parçayı belirlemekten daha fazlasıdır. Aynısını OnResume geri aramalarınıza dahil edebilirsiniz


0

Bu yöntem benim için çalışıyor.

private fun selectBottomNavigationViewMenuItem(bottomNavigationView : BottomNavigationView,@IdRes menuItemId: Int) {
            bottomNavigationView.setOnNavigationItemSelectedListener(null)
            bottomNavigationView.selectedItemId = menuItemId
            bottomNavigationView.setOnNavigationItemSelectedListener(this)
        }

Misal

 override fun onBackPressed() {
        replaceFragment(HomeFragment())
        selectBottomNavigationViewMenuItem(navView, R.id.navigation_home)
    }



private fun replaceFragment(fragment: Fragment) {
        val transaction: FragmentTransaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.frame_container, fragment)
        transaction.commit()
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.