Set initially selected item index/id in BottomNavi

2019-01-22 06:48发布

I've implemented new BottomNavigationView (com.android.support:design:25.0.0) and have no idea how to set selection index or MenuItem id (in my case, mid item should be selected by default). I'm afraid there's no such possibility for now as far as it's too raw yet, but anyway any help will be appreciated. Thanks!

9条回答
对你真心纯属浪费
2楼-- · 2019-01-22 07:29

You can extend BottomNavigationView and use reflection to invoke private methods.

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 {
            BottomNavigationMenuView menuView = (BottomNavigationMenuView) getField(BottomNavigationView.class, "mMenuView");
            OnNavigationItemSelectedListener listener = (OnNavigationItemSelectedListener) getField(BottomNavigationView.class, "mListener");
            try {
                Method method = menuView.getClass().getDeclaredMethod("activateNewButton", Integer.TYPE);
                method.setAccessible(true);
                // activate item.
                method.invoke(menuView, index);
                if (listener != null) {
                    // trigger item select event.
                    listener.onNavigationItemSelected(getMenu().getItem(index));
                }
            } catch (SecurityException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    private Object getField(Class clazz, String fieldName) throws NoSuchFieldException, IllegalAccessException {
        Field f = clazz.getDeclaredField(fieldName);
        f.setAccessible(true);
        return f.get(this);
    }

}
查看更多
该账号已被封号
3楼-- · 2019-01-22 07:33

Set the selected menu item ID using setSelectedItemId:

bottomNavigationView.setSelectedItemId(R.id.item_id);

This method started being available from Android Support Library 25.3.0.

查看更多
SAY GOODBYE
4楼-- · 2019-01-22 07:33

The only solution that worked for me is:

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

Simply performing click does the trick. Hope we'll have extra methods/properties in future releases.

UPD:

As user5968678 mentioned, new method was added since Android Support Library v25.3.0:

bottomNavigationView.setSelectedItemId(R.id.item_id);

so use in instead :)

查看更多
小情绪 Triste *
5楼-- · 2019-01-22 07:39

Stop using Reflection! It is bad!

Well, while the support library does not gives us the option to select the item from the BottomNavigationView to be displayed on the first time when it is visible, we have two possibilities:

First, using loop:

private void setupBottomNavigationView() {
    // Get the menu from our navigationBottomView.
    Menu bottomNavigationViewMenu = bottomNavigationView.getMenu();
    // Uncheck the first menu item (the default item which is always checked by the support library is at position 0).
    bottomNavigationMenu.findItem(R.id.action_one).setChecked(false);
    // Check the wished first menu item to be shown to the user.
    bottomNavigationMenu.findItem(R.id.action_two).setChecked(true);

    bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {

    Menu bottomNavigationMenu = bottomNavigationView.getMenu();
            for (int i = 0; i < bottomNavigationMenu.size(); i++) {
                if (item.getItemId() != bottomNavigationMenu.getItem(i).getItemId()) {
                    bottomNavigationMenu.getItem(i).setChecked(false);
                }
            }

            switch (item.getItemId()) {
                case R.id.action_one :
                    replaceFragment(new OneFragment());
                    break;
                case R.id.action_two :
                    replaceFragment(new TwoFragment());
                    break;
                case R.id.action_three :
                    replaceFragment(new ThreeFragment());
                    break;
            }
            return false;
        }
    });
}

Second, without loop but with a class variable (because the logic is done from within inner class) :

private void setupBottomNavigationView() {
    // Get the menu from our navigationBottomView.
    Menu bottomNavigationViewMenu = bottomNavigationView.getMenu();
    // Uncheck the first menu item (the default item which is always checked by the support library is at position 0).
    bottomNavigationViewMenu.findItem(R.id.action_one).setChecked(false);
    // Check the wished first menu item to be shown to the user. Also store that menu item on a variable to control when a menu item must be unchecked.
    mActiveBottomNavigationViewMenuItem = bottomNavigationViewMenu.findItem(R.id.action_two).setChecked(true);

    bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem selectedMenuItem) {
            switch (selectedMenuItem.getItemId()) {
                case R.id.action_one :
                    replaceFragment(new OneFragment());
                    break;
                case R.id.action_two :
                    replaceFragment(new TwoFragment());
                    break;
                case R.id.action_three :
                    replaceFragment(new ThreeFragment());
                    break;
            }

            if (selectedMenuItem != mActiveBottomNavigationViewMenuItem){
                mActiveBottomNavigationViewMenuItem.setChecked(false);
                mActiveBottomNavigationViewMenuItem = selectedMenuItem;
            }

            return false;
        }
    });
}

private MenuItem mActiveBottomNavigationViewMenuItem;

When the setupBottomNavigationView() method is executed? In Activity onCreate() method, take a look:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // ...
    setupBottomNavigationView();
}

Simple and without extensive code.

Hope it helps!

查看更多
太酷不给撩
6楼-- · 2019-01-22 07:40

If you're using listener, like default implementation in android studio, try this:

BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
Integer indexItem = 4;
navigation.getMenu().getItem(indexItem).setChecked(true);
mOnNavigationItemSelectedListener.onNavigationItemSelected(navigation.getMenu().getItem(indexItem));
查看更多
一夜七次
7楼-- · 2019-01-22 07:40

I believe the question in this context is being viewed in different contexts basing on answers here. According to assessment, whats required is ability to focus on specific BottomNavigationView item (definitely in new class holding different fragments).

Now, you could have BottomNavigationView OR Buttons or Anything clickable to launch new activity on intent : - i.e

Intent intent = new Intent(getActivity(), New_Activity.class);
    intent.putExtra("EXTRA_PAGE, 1);
    startActivityForResult(intent, 30);

Then -in our New_Activity, we receive the intent-

Intent intent = getIntent(); int page = intent.getExtras().getInt("EXTRA_PAGE);

We then loop over the page variable to find the number/Index for which the current BottomNavigationView is reflecting , THEN we set our focus menu item (assuming your BottomNavigationView has Menu Item for its display)

     if(page == 1) {
         currentselect = new Pending();
            bottomNavigationView.getMenu().getItem(0).setChecked(true);
}

This answers the question above. The rest of Fragment switch is handled well by number of posts above by invoking :

bottomNavigationView.setOnNavigationItemSelectedListener(navListener);

Then something like :

   private BottomNavigationView.OnNavigationItemSelectedListener navListener =
        new BottomNavigationView.OnNavigationItemSelectedListener(){
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                Fragment selectedFrag = null;
                switch (item.getItemId()) {
                    case R.id.pending:
                        selectedFrag = new Pending();
                        break;
                    case R.id.onTransmit:
                        selectedFrag = new inTransmit();
                        break;
                    case R.id.complete:
                        selectedFrag = new Complete();
                        break;
                }

                getSupportFragmentManager().beginTransaction().replace(R.id.select_field, selectedFrag).commit();

                return true;
            }
        };

NOTE: Using BottomNavigationView and ContentFrameLayout is soo economical and will slash down your code to over 50 % unlike using likes of ViewPager and Tablayout

查看更多
登录 后发表回答