Android BottomNavigationView에서 선택한 항목 설정


123

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

감사!


1
방금 소스를 살펴 봤는데 같은 질문이 있습니다. 선택한 항목을 설정하는 방법이없는 것 같고 BottomNavigationView내부 상태 저장을 수행하지 않는 것 같습니다. 아마도 이것이 향후 업데이트에 포함될 것으로 예상합니다. 여기에 (일부 추가 정보를 포함) 중복 : stackoverflow.com/questions/40236786/...
팀 Malseed

답변:


171

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

중대한

당신은 반드시 이미 (경우에 당신이 프로그래밍 할) 메뉴에있는 모든 항목을 추가하고 (난 당신이 메서드를 호출 할 때 실행할 리스너에서 코드를하려는 생각) setSelectedItemId를 호출하기 전에 리스너를 설정했습니다. 메뉴 항목을 추가하고 리스너를 설정하기 전에 setSelectedItemId를 호출하면 아무 일도 일어나지 않습니다.


3
이것은 작동하지 않고 탭 자체 만 업데이트하고 setOnNavigationItemSelectedListener 이벤트를 트리거하지 않습니다.
TjerkW

1
행동을 정의하지 않았다면 onTabSelected분명히 아무것도하지 않을 것입니다. 문서 읽기-> 선택한 메뉴 항목 ID를 설정합니다. 이것은 항목을 탭하는 것과 동일하게 작동합니다. 그것은 안드로이드 개발자 출신
리카르도

1
나는 당신이 무엇을 잘못하고 있는지 디버깅하고 검토하는 것이 좋습니다. 이미 세 개의 BottomNavigationView 응용 프로그램을 구현했으며이 방법에 문제가 없었습니다.
Ricardo

그 조각에 입력하는 동안 나는 내 조각이를 추가 할 때 @Ricardo, 응용 프로그램이 중단있어
수빈 바부

1
제 경우에는 프로그래밍 방식으로 navigationMenu를 만들고 있었기 때문에 작동하지 않았습니다. 건설 중에 클릭이 작동하지 않았습니다. 메뉴에 모든 항목이 추가 된 후 setSelectedItemId () 호출이 작동했습니다.
Pedro Romão 2018

53

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

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

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


4
이것은 문제에 관한 해킹입니다. 필요한 것을 수행 할 수있는 라이브러리 자체의 메소드가 있습니다. 그런 다음 그것의 수 없다면 당신은 잘못을하고 있기 때문에
리카르도

47

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


나던 Menu menu = bottomNavigationView.getMenu();소위, 메뉴의 복사본을 반환 bottomNavigationView객체가 영향을받지 않습니다?
最白目

1
@dan 소스에 따라 클래스 속성 mMenu이 아닌 사본을 반환 android.googlesource.com/platform/frameworks/support/+/master/...
비아체슬라프

6
당신은 적어도 26.1.0 / 27.1.0에 선택 해제 다른 항목에 필요하지 않습니다
Jemshit Iskenderov

선택을 취소하지 않는다, 그것은을 강조합니다
djdance

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

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


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 버전부터 setSelectedItemId()\ o / 를 호출 할 수 있습니다.


5

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

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


3

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

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

3
반사는 나쁜 생각입니다!
Filipe Brito

이 경우에는 performClick이 반사, imho보다 낫습니다.
Lassi Kinnunen

3

프로그래밍 방식으로 선택을 수행하는 다른 방법을 추가하는 것뿐입니다. 이것은 아마도 처음에 의도 한 것이거나 나중에 추가되었을 수 있습니다.

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

performIdentifierAction소요 Menu항목 ID 및 플래그.

자세한 내용은 설명서 를 참조하십시오.


이것은 메뉴 항목에 속하는 작업을 수행하는 것처럼 보이지만 메뉴 항목이 선택된 상태로 표시되지는 않습니다. 나는 후자가 OP가 원하는 것이라고 생각했지만 긍정적이지 않습니다.
LarsH

3

SupportLibrary 25.1.0에서 수정 된 것 같습니다. :) 편집 : 화면을 회전 할 때 선택 상태가 저장되는 문제가 수정 된 것 같습니다.


1
방금 25.1.1로 업데이트했습니다. 문제는 여전히 존재합니다.
Xi Wei

3

API 25 이상에서는 setSelectedItemId (menu_item_id)를 사용할 수 있지만 API 25에서는 메뉴를 사용하여 핸들을 얻은 다음 setChecked를 Checked 특정 항목으로 설정해야합니다.


3

메뉴 ID별로 선택한 하단 탐색 메뉴 항목을 설정하는 데 사용합니다.

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

2

코드를 수정하고 싶지 않습니다. 그렇다면 BottomNavigationViewEx 를 사용해 보는 것이 좋습니다 。

당신은 메소드를 호출 setCurrentItem(index);하고 getCurrentItem()

이미지를 보려면 여기를 클릭하십시오.


2

사용하다

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


1

performClick 메소드를 시도해 볼 수 있습니다.

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

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

솔루션의 유일한 '마이너스'는을 사용 MenuItemImpl하는 것인데, 이는 라이브러리에 대해 '내부'(공개이지만)입니다.


0

단편 인수를 동적으로 전달해야하는 경우이 작업을 수행하십시오.

여기에는 (대부분 반복되거나 오래된) 답변이 많이 있지만 그중 어느 것도 매우 일반적인 요구를 처리하지 않습니다 . 탭에로드 된 Fragment에 다른 인수를 동적으로 전달하는 것 입니다.

를 사용하여로드 된 프래그먼트에 다른 인수를 동적으로 전달할 수 없으며 setSelectedItemId(R.id.second_tab)이는 결국 static OnNavigationItemSelectedListener. 이 제한을 극복하기 위해 MainActivity탭이 포함 된 내에서이 작업을 수행했습니다 .

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()메서드는 평소와 같이 구현됩니다.

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

이게 도움이 되길 바란다

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

이는 해당 하단 탐색 메뉴 항목과 동시에로드되는 기본 조각을 결정하는 것입니다. OnResume 콜백에 동일한 것을 포함 할 수 있습니다.


0

이 방법은 저에게 효과적입니다.

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

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

-1

반사는 나쁜 생각입니다.

요점으로 향하십시오 . 선택을 수행하지만 콜백을 호출하는 메소드가 있습니다.

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

    }

callOnClick()대신 사용 합니다 performClick(). 이렇게하면 performClick()어차피 작동하지 않는 사운드를 비활성화 할 필요가 없습니다 .
arekolek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.