web-dev-qa-db-ja.com

アクティビティ間でBottomNavigationViewを使用して押したときにアイテムを強調表示する方法は?

アプリにボトムナビゲーションビューを追加しましたが、フラグメントではなくアクティビティ間にボトムナビゲーションビューが必要なので、このコードをJavaの3つのアクティビティすべてに追加しました。

電話で2番目または3番目を選択すると、すべてが正しくなりますが、問題はハイライトが最初の項目に移動することです。

押すアイテムを強調表示する必要があります。

フラグメントを使用しましたが、完全に動作しますが、フラグメントを使用する初心者なので、アクティビティを使用しています

最初のアクティビティコードは次のとおりです。

BottomNavigationView mBottomNavigation;

    mBottomNavigation =(BottomNavigationView) findViewById(R.id.BottomNavigator);

    mBottomNavigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()){
                case R.id.Nav_Second:
                    Intent Second= new Intent(First.this, Second.class);
                    startActivity(Second);
                    break;
                case R.id.Nav_Third:
                    Intent Third= new Intent(First.this, Third.class);
                    startActivity(Third);
                    break;
            }

            return true;
        }
    });


}}

2番目のアクティビティは次のとおりです。

BottomNavigationView mBottomNavigation;

    mBottomNavigation =(BottomNavigationView) findViewById(R.id.BottomNavigator);

    mBottomNavigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()){
                case R.id.Nav_First:
                    Intent First= new Intent(Second.this, First.class);
                    startActivity(First);
                    break;
                case R.id.Nav_Third:
                    Intent Third= new Intent(Second.this, Third.class);
                    startActivity(Third);
                    break;
            }

            return true;
        }
    });

}}

3番目のアクティビティは次のとおりです。

BottomNavigationView mBottomNavigation;

    mBottomNavigation =(BottomNavigationView) findViewById(R.id.BottomNavigator);

    mBottomNavigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()){
                case R.id.Nav_First:
                    Intent First= new Intent(Third.this, First.class);
                    startActivity(First);
                    break;
                case R.id.Nav_Second:
                    Intent Second= new Intent(Third.this, Second.class);
                    startActivity(Second);
                    break;
            }

            return true;
        }
    });


}}

Xmlは3つのアクティビティで同じです:

<Android.support.design.widget.BottomNavigationView
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:id="@+id/BottomNavigator"
        Android:background="@color/colorPrimaryDark"
        Android:layout_alignParentBottom="true"
        app:itemTextColor="@drawable/item_bg"
        app:itemIconTint="@drawable/item_bg"
        app:menu="@menu/navigate_items">
    </Android.support.design.widget.BottomNavigationView>
17
7uthaifah

BottomNavigationViewは、タブを表すアクティビティで使用できます。重要なのは、各アクティビティでナビゲーションビューコンポーネントを繰り返し、各アクティビティのコードでナビゲーションコンポーネントを制御することです。ナビゲーションアイテムのクリックで適切なアクティビティを開始し、アクティビティの開始後に適切なナビゲーションアイテムを選択します。

新しいアクティビティが前のアクティビティに置き換わる前にタブ切り替えアニメーションが完了するのを遅らせるため、新しく選択したアクティビティ(タブ)を開始する必要があります。

私のアプローチは、タブを表すすべてのアクティビティが、共通の動作を実装する同じBaseActivityクラスから継承することでした。

これは、BaseActivityの例のコードです。

public abstract class BaseActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {

    protected BottomNavigationView navigationView;

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

        navigationView = (BottomNavigationView) findViewById(R.id.navigation);
        navigationView.setOnNavigationItemSelectedListener(this);
    }

    @Override
    protected void onStart() {
        super.onStart();
        updateNavigationBarState();
    }

    // Remove inter-activity transition to avoid screen tossing on tapping bottom navigation items
    @Override
    public void onPause() {
        super.onPause();
        overridePendingTransition(0, 0);
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        navigationView.postDelayed(() -> {
            int itemId = item.getItemId();
            if (itemId == R.id.navigation_home) {
                startActivity(new Intent(this, HomeActivity.class));
            } else if (itemId == R.id.navigation_dashboard) {
                    startActivity(new Intent(this, DashboardActivity.class));
            } else if (itemId == R.id.navigation_notifications) {
                    startActivity(new Intent(this, NotificationsActivity.class));
            }
            finish();
        }, 300);
        return true;
    }

    private void updateNavigationBarState(){
        int actionId = getNavigationMenuItemId();
        selectBottomNavigationBarItem(actionId);
    }

    void selectBottomNavigationBarItem(int itemId) {
        Menu menu = navigationView.getMenu();
        for (int i = 0, size = menu.size(); i < size; i++) {
            MenuItem item = menu.getItem(i);
            boolean shouldBeChecked = item.getItemId() == itemId;
            if (shouldBeChecked) {
                item.setChecked(true);
                break;
            }
        }
    }

    abstract int getContentViewId();

    abstract int getNavigationMenuItemId();

}

これはAndroid Studioの下部ナビゲーションアクティビティテンプレートに基づく私の例です:

https://github.com/ddekanski/BottomNavigationViewBetweenActivities

17
javaxian

まだこれを探している人にとって、各アクティビティを拡張するという@javazianの答えは、私の意見では本当にやり過ぎです。

より簡潔な解決策は、ナビゲーションメニューを取得し、関連するメニュー項目を手動で確認することです。

次の例では、INSERT_INDEX_HEREをメニュー項目のインデックスに置き換える必要があることに注意してください(たとえば、左端のメニュー項目のインデックスは0になります)。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_connections);

    BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

    // Ensure correct menu item is selected (where the magic happens)
    Menu menu = navigation.getMenu();
    MenuItem menuItem = menu.getItem(INSERT_INDEX_HERE);
    menuItem.setChecked(true);
}
6
hardanger

BottomNavigationViewをアクティビティで絶対に使用できますが、お勧めしません。より良いのは、フラグメントで使用することです。主な利点は次のとおりです。

  • BottomNavigationViewのアニメーション(アクティビティの場合、い遅延なし)
  • フラグメントの状態を簡単に維持
  • 柔軟なバックスタック

しかし、アクティビティに固執したい場合は、@ javaxianの回答は非常に良いですが、改善することができます。

  1. レイアウトファイルに適切なIDのBottomNavigationがない場合、例外が発生します。より良いのは、ナビゲーションを伴うアクティビティ用の共通のレイアウトファイルを持つことです。

ソリューション

1)BaseActivityの名前をBaseNavigationActivityに変更します

2)すべてのアクティビティに対して単一のレイアウトファイルを作成し(たとえば_activity_navigation.xml_)、BaseNavigationActivity setContentView(R.layout.activity_navigation);を明示的に呼び出します

3)abstract int getContentViewId();を削除します

  1. selectBottomNavigationBarItem(int itemId)のコードはオーバーヘッドです。もっと簡単にできます

ソリューション(Kotlinで):

_private fun selectBottomNavigationBarItem(itemId: Int) {
    val menuItem = navigationView.menu.findItem(itemId)
    menuItem.isChecked = true
}
_
5
Vlad Sonkin

開始時に各アクティビティでsetSelectedItemIdを使用できます。

bottomNavigationView.setSelectedItemId(R.id.menu_item_id);

ここでR.id.menu_item_idはmenu/navigate_itemsにあります

2
Oyeme