サポートライブラリの新しいAndroid.support.design.widget.BottomNavigationView
を使用しています。コードから現在の選択内容を設定する方法を教えてください。画面を回転させた後、選択が最初の項目に戻ることに気づきました。もちろん、BottomNavigationView
関数の現在のonPause
の状態を「保存」する方法、およびonResume
に復元する方法も教えてください。
ありがとうございます。
SupportLibrary 25.1.0で修正されているようです:)編集:画面を回転させたとき、選択の状態が保存されるのは修正されたようです。
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を呼び出す前に、MUSTすべての項目がメニューに追加され、Listenerが設定されていることメニュー項目を追加してリスナーを設定する前に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
を使用して再生し、適切な解決策を見つけることができたと思います。
25.3.0以降のバージョンでsetSelectedItemId()
\o /を呼び出すことが可能になりました
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bottomNavigationView.setOnNavigationItemSelectedListener(this);
Menu menu = bottomNavigationView.getMenu();
this.onNavigationItemSelected(menu.findItem(R.id.action_favorites));
}
bottomNavigationView.setSelectedItemId(R.id.action_item1);
action_item1
はメニュー項目IDです。
BottomNavigationMenu ItemsにAndroid:enabled="true"
を追加します。
そして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"/>
API 25より上ではsetSelectedItemId(menu_item_id)を使用できますが、API 25ではユーザーメニューを別の方法で処理し、setCheckedをChecked特定の項目にする必要があります
選択的にプログラム的に実行するための別の方法を追加するだけです - これはおそらくそもそも意図していたものであるか、または後で追加されたのかもしれません。
Menu bottomNavigationMenu = myBottomNavigationMenu.getMenu();
bottomNavigationMenu.performIdentifierAction(selected_menu_item_id, 0);
performIdentifierAction
はMenu
項目IDとフラグを取ります。
詳しくは ドキュメント を参照してください。
私はあなたのコードを修正したくないのです。もしそうなら、試してみることをお勧めします BottomNavigationViewEx 。
代わりにメソッドsetCurrentItem(index);
とgetCurrentItem()
を呼び出します。
私はBottomNavigationViewでページを選択する信頼できる方法がないという事実についてグーグルにバグを作りました: https://code.google.com/p/Android/issues/detail?id=233697
NavigationViewには、似たような問題があるようです。新しいsetCheckedItem()メソッドを追加することで解決しました。
PerformClickメソッドを試すことができます。
View view = bottomNavigationView.findViewById(R.id.YOUR_ACTION);
view.performClick();
フラグメントの引数を動的に渡す必要がある場合
ここには多くの(ほとんど繰り返されるか古い)答えがありますが、どれも非常に一般的なニーズを処理しません:タブにロードされたフラグメントに異なる引数を動的に渡す。
静的なOnNavigationItemSelectedListener
を呼び出すsetSelectedItemId(R.id.second_tab)
を使用して、ロードされたフラグメントに異なる引数を動的に渡すことはできません。この制限を克服するために、タブを含む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
}
}
}
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
を使用することです。これはライブラリの「内部」です(ただしパブリック)。