developer tip

Android BottomNavigationView에서 선택한 항목 설정

optionbox 2020. 8. 26. 07:46
반응형

Android BottomNavigationView에서 선택한 항목 설정


android.support.design.widget.BottomNavigationView지원 라이브러리 의 새 기능 사용하고 있습니다. 코드에서 현재 선택을 어떻게 설정할 수 있습니까? 화면을 회전 한 후 선택 항목이 첫 번째 항목으로 다시 변경된다는 것을 깨달았습니다. 물론 그것은 도움도 것, 누군가가 말해 수 있다면, 방법에의 현재 상태를 "저장" BottomNavigationViewonPause기능과 그것을 복원하는 방법 onResume.

감사!


API 25.3.0부터 탭한 것처럼 setSelectedItemId(int id)항목을 선택된 것으로 표시하는 방법이 도입되었습니다 .

문서에서 :

선택한 메뉴 항목 ID를 설정합니다. 이것은 항목을 탭하는 것과 동일하게 작동합니다.

코드 예 :

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

중대한

당신은 반드시 이미 메뉴에 모든 항목을 추가하고 그래서 BottomNavigationView는 해당 코드의 동작을 실행할 수 setSelectedItemId를 호출하기 전에 리스너를 설정했습니다. 메뉴 항목을 추가하고 리스너를 설정하기 전에 setSelectedItemId를 호출하면 아무 일도 일어나지 않습니다.


프로그래밍 방식으로 BottomNavigationBar 항목을 클릭하려면 다음을 사용해야합니다.

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

이렇게하면 레이블이있는 모든 항목이 올바르게 정렬됩니다.


여전히 SupportLibrary <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내비게이션 뷰 와 동일하게 플레이하고 적절한 솔루션을 찾을 수 있다고 생각합니다 .


bottomNavigationView.setSelectedItemId(R.id.action_item1);

action_item1메뉴 항목 ID는 어디에 있습니까 ?


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

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

이제 25.3.0 버전부터 setSelectedItemId()\ o / 를 호출 할 수 있습니다.


android:enabled="true"BottomNavigationMenu 항목에 추가 합니다.

그런 다음 다음 bottomNavigationView.setOnNavigationItemSelectedListener(mListener)을 수행하여 선택한대로 설정 하고 설정합니다.bottomNavigationView.selectedItemId = R.id.your_menu_id


이는 향후 업데이트에 추가 될 것입니다. 그러나 그 동안 이것을 달성하기 위해 반사를 사용할 수 있습니다.

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"/>

Above API 25 you can use setSelectedItemId(menu_item_id) but under API 25 you must do differently, user Menu to get handle and then setChecked to Checked specific item


I you don't want to modify your code. If so, I recommended you to try BottomNavigationViewEx

You just need replace call a method setCurrentItem(index); and getCurrentItem()

Click here to view the image


Just adding another way to perform a selection programatically - this is probably what was the intention in the first place or maybe this was added later on.

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

The performIdentifierAction takes a Menu item id and a flag.

See the documentation for more info.


Seems to be fixed in SupportLibrary 25.1.0 :) Edit: It seems to be fixed, that the state of the selection is saved, when rotating the screen.


I made a bug to Google about the fact that there's no reliable way to select the page on a BottomNavigationView: https://code.google.com/p/android/issues/detail?id=233697

NavigationView apparently had a similar issue, which they fixed by adding a new setCheckedItem() method.


You can try the performClick method :

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

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

The only 'minus' of the solution is using MenuItemImpl, which is 'internal' to library (though public).


IF YOU NEED TO DYNAMICALLY PASS FRAGMENT ARGUMENTS DO THIS

There are plenty of (mostly repeated or outdated) answers here but none of them handles a very common need: dynamically passing different arguments to the Fragment loaded into a tab.

You can't dynamically pass different arguments to the loaded Fragment by using setSelectedItemId(R.id.second_tab), which ends up calling the static OnNavigationItemSelectedListener. To overcome this limitation I've ended up doing this in my MainActivity that contains the tabs:

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

The ArticleFragment.newInstance() method is implemented as usual:

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

}

Reflection is bad idea.

Head to this gist. There is a method that performs the selection but also invokes the callback:

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

    }

참고URL : https://stackoverflow.com/questions/40202294/set-selected-item-in-android-bottomnavigationview

반응형