Как выделить элемент при нажатии с помощью BottomNavigationView между действиями?

Я добавил представление нижней навигации для своего приложения, но мне нужно представление нижней навигации между действиями, а не фрагментом, поэтому я добавил этот код в Java для всех моих трех действий.

Когда я выбираю "Второй" или "Третий" на своем телефоне, все идет правильно, но проблема в том, что выделение переходит к первому элементу.

Мне нужно выделить элемент, который я нажимаю.

Я использовал фрагмент, и он отлично работает, но я все еще новичок в использовании фрагмента, поэтому я использую действия.

Первый код активности:

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


}}

Второй вид деятельности:

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

}}

Третий вид деятельности:

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>


person 7uthaifah    schedule 19.01.2017    source источник
comment
Если я что-то не упустил, это хороший сценарий для использования фрагментов (и он отлично работает), так почему бы не придерживаться этого?   -  person Matt M    schedule 19.01.2017
comment
потому что фрагмент немного сложнее, чем основные действия...   -  person 7uthaifah    schedule 19.01.2017
comment
как я могу расширить приложение с помощью AppCompatActivity   -  person 7uthaifah    schedule 19.01.2017
comment
Попробуйте посмотреть на этот пример   -  person Matt M    schedule 19.01.2017
comment
Спасибо за помощь бро...   -  person 7uthaifah    schedule 19.01.2017
comment
Спасибо, Мэтт М, за помощь, наконец-то я нашел решение...   -  person 7uthaifah    schedule 19.01.2017
comment
Я рад это слышать. Вам следует рассмотреть возможность добавления ответа, чтобы он мог помочь другим.   -  person Matt M    schedule 19.01.2017


Ответы (4)


Вы можете использовать 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 Bottom Navigation Activity:

https://github.com/ddekanski/BottomNavigationViewBetweenActivities

person javaxian    schedule 15.03.2017
comment
Я видел, как вы кодируете, как поддерживать состояния фрагментов внутри действий, когда я нажимаю вкладку 1, я прокручиваю вниз, затем нажимаю вкладку 2 и нажимаю вкладку 1, она прокручивает меня вверх? - person Munish Kapoor; 30.03.2017
comment
Вместо использования overridePendingTransition(0, 0); в onPause() используйте ‹item name=android:windowAnimationStyle›@null‹/item› в теме. Полное решение см. здесь: stackoverflow.com/questions/ 6972295/ - person Shunan; 09.03.2018
comment
Хороший ответ, но любой способ не воссоздавать действие, если оно уже создано. Например, при таком подходе, если я нахожусь на двух или более уровнях в глубине определенного действия, и я выбираю другое действие, и они возвращаются к ранее выбранному действию, вызов startActivity воссоздает его и, следовательно, возвращает меня на верхний уровень эта деятельность - person saintjab; 31.03.2019

Для тех, кто все еще ищет это, ответ @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);
}
person hardanger    schedule 09.02.2018

Вы абсолютно можете использовать BottomNavigationView с действиями, но это не рекомендуется. Лучше использовать его с фрагментами, основные преимущества:

  • Анимация в BottomNavigationView (без уродливой задержки в случае Activity)
  • Легко поддерживать состояние фрагментов
  • Гибкая задняя стенка

Но если вы хотите придерживаться Activity, то ответ @javaxian очень хорош, но мы можем его улучшить:

  1. Если в нашем файле макета нет BottomNavigation с правильным идентификатором, у нас будет исключение. Лучше иметь общий файл макета для действий с навигацией.

Решение:

1) Переименуйте BaseActivity в BaseNavigationActivity.

2) Создайте один файл макета для всех ваших действий (например, activity_navigation.xml) и явно вызовите BaseNavigationActivity setContentView(R.layout.activity_navigation);

3) Удалить abstract int getContentViewId();

  1. Код в selectBottomNavigationBarItem(int itemId) является накладным, мы можем сделать его гораздо проще

Решение (в Котлине):

private fun selectBottomNavigationBarItem(itemId: Int) {
    val menuItem = navigationView.menu.findItem(itemId)
    menuItem.isChecked = true
}
person vladsonkin.com    schedule 22.03.2018

Вы можете использовать setSelectedItemId в каждом действии при его запуске.

bottomNavigationView.setSelectedItemId(R.id.menu_item_id);

где R.id.menu_item_id находится в menu/navigate_items

person Oyeme    schedule 12.05.2019