it-swarm.com.ru

Как правильно управлять нижней навигацией при нажатой спине

Я работаю над нижней панелью навигации, но я не получаю идеально нижней панели навигации.

Мой MainActivity класс:

public class MainActivity extends AppCompatActivity {

    private static final String SELECTED_ITEM = "selected_item";

    private BottomNavigationView bottomNavigationView;
    private Toolbar toolbar;
    private MenuItem menuItemSelected;
    private int mMenuItemSelected;


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

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);
        bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                selectFragment(item);
                return true;
            }
        });

        //Always load first fragment as default
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.frameLayout, new AnnouncementFragment());
        fragmentTransaction.commit();

        if (savedInstanceState != null) {
            mMenuItemSelected = savedInstanceState.getInt(SELECTED_ITEM, 0);
            menuItemSelected = bottomNavigationView.getMenu().findItem(mMenuItemSelected);
        } else {
            menuItemSelected = bottomNavigationView.getMenu().getItem(0);
        }

        selectFragment(menuItemSelected);
    }

    private void selectFragment(MenuItem item) {
        Fragment fragment = null;
        Class fragmentClass;
        switch (item.getItemId()) {
            case R.id.action_announcement:
                fragmentClass = AnnouncementFragment.class;
                break;
            case R.id.action_menu:
                fragmentClass = MenuFragment.class;
                break;
            case R.id.action_menu_reports:
                fragmentClass = ReportFragment.class;
                break;
            case R.id.action_setting:
                fragmentClass = SettingFragment.class;
                break;

            default:
                fragmentClass = AnnouncementFragment.class;
        }

        try {
            fragment = (Fragment) fragmentClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.frameLayout, fragment).commit();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putInt(SELECTED_ITEM, mMenuItemSelected);
        super.onSaveInstanceState(outState);
    }

И моя спина нажата тоже не работает

 @Override
    public void onBackPressed() {
        MenuItem homeItem = bottomNavigationView.getMenu().getItem(0);
        if (mMenuItemSelected != homeItem.getItemId()) {
            selectFragment(homeItem);
        } else {
            super.onBackPressed();
        }
    }

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

Здесь я прилагаю мой результат, который я получаю на AVD  First I

 Another Selection

11
Venky

В соответствии с руководящими принципами для Материальный дизайн

На Android кнопка «Назад» не перемещается между нижним панель навигации просмотров.

EDIT: ссылка «Дизайн материала» больше не упоминает поведение кнопки «Назад».

Нажав кнопку «Назад», вы можете выйти из приложения, которое используется по умолчанию, например, в Google Photo ...

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content, fragment);
// note: there is NOT a addToBackStack call
fragmentTransaction.commit();

... или привести пользователя в домашний раздел, а затем, если его снова нажать, на выходе.

Лично я нахожу эту последнюю модель намного лучше.

Чтобы получить его без переопределения onBackPressed, вам нужно идентифицировать домашний фрагмент и отличить его от all других

navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.navigation_home:
                viewFragment(new HomeFragment(), FRAGMENT_HOME);
                return true;
            case R.id.navigation_page_1:
                viewFragment(new OneFragment(), FRAGMENT_OTHER);
                return true;
            case R.id.navigation_page_2:
                viewFragment(new TwoFragment(), FRAGMENT_OTHER);
                return true;
        }
        return false;
    }
});

Теперь вам нужно написать метод viewfragment, который должен:

  1. Узнайте, сколько фрагментов в стеке перед переменной commit
  2. Если фрагмент not «home type», сохраните его в стеке до commit

  3. Добавьте OnBackStackChangedListener, который при уменьшении стека, (Т.е. когда я нажал назад), удалит все фрагменты not «home type» ( POP_BACK_STACK_INCLUSIVE ), приведя нас к домашний фрагмент

Ниже полный метод с комментариями

private void viewFragment(Fragment fragment, String name){
    final FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.content, fragment);
    // 1. Know how many fragments there are in the stack
    final int count = fragmentManager.getBackStackEntryCount();
    // 2. If the fragment is **not** "home type", save it to the stack
    if( name.equals( FRAGMENT_OTHER) ) {
        fragmentTransaction.addToBackStack(name);
    }
    // Commit !
    fragmentTransaction.commit();
    // 3. After the commit, if the fragment is not an "home type" the back stack is changed, triggering the
    // OnBackStackChanged callback
    fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            // If the stack decreases it means I clicked the back button
            if( fragmentManager.getBackStackEntryCount() <= count){
                // pop all the fragment and remove the listener
                fragmentManager.popBackStack(FRAGMENT_OTHER, POP_BACK_STACK_INCLUSIVE);
                fragmentManager.removeOnBackStackChangedListener(this);
                // set the home button selected
                navigation.getMenu().getItem(0).setChecked(true);
            }
        }
    });
}
9
marco

Попробуй это 

@Override
    public void onBackPressed() {
        BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
        int seletedItemId = bottomNavigationView.getSelectedItemId();
        if (R.id.home != seletedItemId) {
            setHomeItem(MainActivity.this);
        } else {
            super.onBackPressed();
        }
    }

public static void setHomeItem(Activity activity) {
    BottomNavigationView bottomNavigationView = (BottomNavigationView)
            activity.findViewById(R.id.navigation);
    bottomNavigationView.setSelectedItemId(R.id.home);
}
9
Shailesh Bandil
@Override
    public void onBackPressed() {
        BottomNavigationView mBottomNavigationView = findViewById(R.id.navigation);
        if (mBottomNavigationView.getSelectedItemId() == R.id.navigation_home)
        {
            super.onBackPressed();
            finish();
        }
        else
        {
            mBottomNavigationView.setSelectedItemId(R.id.navigation_home);
        }
    }
5
Vasu

onBackPressed не работает для меня. Так что это я использовал.

 @Override
 protected void onResume() {
    super.onResume();
    bottomNavigationView.getMenu().getItem(0).setChecked(true);
 }
4
Thriveni

Это может быть немного поздно, но я думаю, что лучший способ сделать это так просто.

 @Override
public void onBackPressed() {
    if (mBottomNavigationView.getSelectedItemId() == R.id.action_home) {
        super.onBackPressed();
    } else {
        mBottomNavigationView.setSelectedItemId(R.id.action_home);
    }
}

Я надеюсь, что это помогает и счастливое кодирование :)

3
Fahd Al-Qahtani

Лучше всего: когда кнопка «Домой» закрыта, а кнопка «Домой» снова нажата.

Ниже я положил свой код:

сначала я загружаю кнопку домой в навигации.

private void loadFragment(Fragment fragment) {
    Toast.makeText(this, "load", Toast.LENGTH_SHORT).show();
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.frame_container, fragment, TAG_FRAGMENT);
    transaction.commit();
}

и помните, что не вызывайте addToBackStack() ., а затем обработайте ситуацию с помощью onBackPressed():

@Override
public void onBackPressed() {
    if (navigation.getSelectedItemId() == R.id.bottomAkhbar) {
        super.onBackPressed();
    } else {
        navigation.setSelectedItemId(R.id.bottomAkhbar);
    }
}
2
ali hoseinpoor

Я столкнулся с той же проблемой, но после этого я получил решение

Сначала вставьте этот код в основной вид деятельности (там, где вы используете нижнюю панель навигации)

BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

А затем создайте класс с именем BottomNavigationViewHelper и вставьте следующий код.

public class BottomNavigationViewHelper {
public static void disableShiftMode(BottomNavigationView view) {
    BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
    try {
        Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
        shiftingMode.setAccessible(true);
        shiftingMode.setBoolean(menuView, false);
        shiftingMode.setAccessible(false);
        for (int i = 0; i < menuView.getChildCount(); i++) {
            BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
            //noinspection RestrictedApi
            item.setShiftingMode(false);
            // set once again checked value, so view will be updated
            //noinspection RestrictedApi
            item.setChecked(item.getItemData().isChecked());
        }
    } catch (NoSuchFieldException e) {
        Log.e("BNVHelper", "Unable to get shift mode field", e);
    } catch (IllegalAccessException e) {
        Log.e("BNVHelper", "Unable to change value of shift mode", e);
    }
}

}

Надеюсь, поможет

1
Rajat Mittal

Я сделал это после того, как попробовал все и все, и в конце концов это сработало -_-. Я вставил этот метод 2 переопределения в каждое действие, которое я просматривал в нижней навигации.

  @Override
protected void onResume() {
    super.onResume();
    bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_Menu_name);
    bottomNavigationView.getMenu().getItem(Menu_item_position).setChecked(true);

}

@Override
protected void onRestart() {
    super.onRestart();
    bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_Menu_name);
    bottomNavigationView.getMenu().getItem(Menu_item_position).setChecked(true);
}
1
Ananna Rahman

Поздний ответ, но здесь это идет.

Допустим, у вас есть BottomNavigation inside MainActivity с 4 фрагментами

  1. Fragmenta 
  2. FragmentB 
  3. FragmentC 
  4. FragmentD

Если вы добавляете каждый фрагмент в backstack следующим образом:

С котлином:

 main_bottom_navigation.setOnNavigationItemSelectedListener { item ->
        var fragment: Fragment? = null
        when (item.itemId) {
            R.id.nav_a -> fragment = FragmentA()
            R.id.nav_b -> fragment = FragmentB()
            R.id.nav_c -> fragment = FragmentC()
            R.id.nav_d -> fragment = FragmentD()
        }

        supportFragmentManager
            .beginTransaction()
            .setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out)
            .replace(R.id.home_content, fragment!!)
            .addToBackStack(fragment.tag)
            .commit()

        true
    }

Вам действительно не нужно переопределять onBackPressed () внутри MainActivity , но явно приводить к каждому фрагменту и назначать BottomNavigation следующим образом:

FragmentA.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    (activity as MainActivity).main_bottom_navigation.menu.getItem(0).isChecked = true
}

FragmentB.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    (activity as MainActivity).main_bottom_navigation.menu.getItem(1).isChecked = true
}

FragmentC.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    (activity as MainActivity).main_bottom_navigation.menu.getItem(2).isChecked = true
}

FragmentD.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    (activity as MainActivity).main_bottom_navigation.menu.getItem(3).isChecked = true
}

Таким образом, backstack фрагмента будет правильно всплывать и даже выходить из приложения, когда достигнет 0.

1
Ispam

По вашему требованию вы будете работать с фрагментами навигации, для этого вы можете использовать Tablayout с пейджером представления и сделать навигацию снизу.

<Android.support.design.widget.TabLayout
        Android:id="@+id/tab_layout"
        Android:layout_width="match_parent"
        Android:layout_height="60dp"></Android.support.design.widget.TabLayout>

а затем настройте viewpager с макетом вкладки и добавьте значок в tablayout в вашей деятельности

tabLayout = (TabLayout) findViewById(R.id.tab_layout);
    viewPager = (ViewPager) findViewById(R.id.controller_pager);
    viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
    viewPager.setOffscreenPageLimit(4);
    tabLayout.setupWithViewPager(viewPager);
    tabLayout.getTabAt(0).setIcon(R.drawable.selector_home);
    tabLayout.getTabAt(1).setIcon(R.drawable.selector_contact);
    tabLayout.getTabAt(2).setIcon(R.drawable.selector_profile);
    tabLayout.getTabAt(3).setIcon(R.drawable.selector_settings);

теперь обрабатывать все вещи по нажатию tablayout, и он будет работать нормально tabLayout.addOnTabSelectedListener (это);

1
pankaj yadav

Используйте addToBackStack Метод при вызове такого фрагмента,

   getSupportFragmentManager().beginTransaction().addToBackStack(null).add(R.id.content_home_nav,newFragment).commit();

Используйте этот код в вашем методе onBackPressed

if (getSupportFragmentManager().getBackStackEntryCount() > 0 ){
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
1
scienticious

Пожалуйста, попробуйте это решение . Я внес изменения в ваш код, указанный в вопросе.

Я предположил, что при первом нажатии на ваше приложение вернется к домашнему фрагменту (в вашем случае фрагмент объявления), и если вы снова нажмете снова, приложение закроется.

Этот поток также будет отражаться в нижней панели навигации.

public class MainActivity extends AppCompatActivity {
private static final String BACK_STACK_ROOT_TAG = "root_home_fragment";
private static final String SELECTED_ITEM = "selected_item";
private Fragment fragment;
private FragmentManager fragmentManager;
private BottomNavigationView bottomNavigationView;
private Toolbar toolbar;
private MenuItem menuItemSelected;
private int mMenuItemSelected;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
        = new BottomNavigationView.OnNavigationItemSelectedListener() {

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        boolean selected = false;
        switch (item.getItemId()) {
            case R.id.action_announcement:
                fragment = AnnouncementFragment.newInstance();
                selected =  true;
                break;
            case R.id.action_menu:
                fragment = MenuFragment.newInstance();
                selected =  true;
                break;
            case R.id.action_menu_reports:
                fragment = ReportFragment.newInstance();
                selected =  true;
                break;
        case R.id.action_setting:
        fragment = SettingFragment.newInstance();
                selected =  true;

        }
        if(fragment !=null){
            fragmentManager = getFragmentManager();
            switch (item.getItemId()) {
              case R.id.action_announcement:
                   // Pop every fragment from backstack including home fragment.
                   fragmentManager.popBackStack(BACK_STACK_ROOT_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                   fragmentManager.beginTransaction()
                            .replace(R.id.content, fragment)
                            .addToBackStack(BACK_STACK_ROOT_TAG)
                            .commit();
                    break;
               default: 

                   fragmentManager.beginTransaction()
                            .replace(R.id.content, fragment)
                            .addToBackStack(null)
                            .commit();  
                   break;
           }
        }
        return selected;
    }

};


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

    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);
    bottomNavigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

    //Always load first fragment as default
    bottomNavigationView.setSelectedItemId(R.id.action_announcement);

    if (savedInstanceState != null) {
        mMenuItemSelected = savedInstanceState.getInt(SELECTED_ITEM, 0);
        menuItemSelected = bottomNavigationView.getMenu().findItem(mMenuItemSelected);
    } else {
        menuItemSelected = bottomNavigationView.getMenu().getItem(0);
    }
}



@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putInt(SELECTED_ITEM, mMenuItemSelected);
    super.onSaveInstanceState(outState);
}

public void onBackPressed() {
    int count = getFragmentManager().getBackStackEntryCount();
    if(count >1){
        // We have lots of fragment on backstack to be popped.
        // Pop till the root fragment.
        getFragmentManager().popBackStack(BACK_STACK_ROOT_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
     bottomNavigationView.setSelectedItemId(R.id.action_announcement);
    }
    else{
        // Close the application when we are on home fragment.
        supportFinishAfterTransition();
    }
}
}
1
Tony

У меня была та же проблема, поэтому я решил свою проблему, используя этот метод: В моем основном задании у меня есть нижняя панель навигации и блок навигации, мне нужно синхронизировать элементы в моем блоке и нижней панели навигации:

Я создал метод для моего основного фрагмента и других: Мой основной заменитель фрагмента:

public void MainFragmentChanger(final Fragment fragment, final String TAG){
    if (main_page_fragment != null){
        fragmentTransaction = myFragmentManager.beginTransaction();
        fragmentTransaction.remove(main_page_fragment).commit();
    }
    if (main_drawer.isDrawerOpen()){
        main_drawer.closeDrawer();
    }
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            main_page_fragment = fragment;
            main_page_fragment.setRetainInstance(true);
            fragmentTransaction = myFragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.main_container, main_page_fragment,TAG);
            fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            fragmentTransaction.commitAllowingStateLoss();
        }
    });
}

и это для моего другого заменителя фрагмента:

public void changeBottomFragment(final Fragment fragment, final String TAG){
    if (main_drawer.isDrawerOpen()){
        main_drawer.closeDrawer();
    }
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            main_page_fragment = fragment;
            main_page_fragment.setRetainInstance(true);
            fragmentTransaction = myFragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.main_container, main_page_fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            fragmentTransaction.commitAllowingStateLoss();
        }
    });
}

поэтому после этого мне нужно синхронизировать элементы как в ящике, так и на панели: Примечание. Я использую ящик для навигации по материалам Майка Пенза и com.ashokvarma.bottomnavigation.BottomNavigationBar для навигационной панели. :

public void changeNavAndBarStats(String tag){
    if (tag == "flash"){
        bottomNavigationBar.selectTab(2,false);
        main_drawer.setSelection(flashcards.getIdentifier(),false);
    }else if (tag == "dic"){
        bottomNavigationBar.selectTab(3,false);
        main_drawer.setSelection(dictionary.getIdentifier(),false);
    }else if (tag == "Home"){
        bottomNavigationBar.selectTab(0,false);
        main_drawer.setSelection(home.getIdentifier(),false);
    }
}

Поэтому я называю свои фрагменты вот так:

MainFragmentChanger(new MainPageFragment(),"Home");
                            bottomNavigationBar.selectTab(0,false);

changeBottomFragment(new FlashCardFragment(),"flash");
                            bottomNavigationBar.selectTab(2,false);

changeBottomFragment(new TranslateFragment(),"dic");
                            bottomNavigationBar.selectTab(3,false);

В конце я вызываю changeNavAndBarStatus в методе onResume моего фрагмента:

((MainPageActivity)getContext()).changeNavAndBarStats("flash");

Это оно! Вы готовы идти!

1
MoeinDeveloper

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

там добавить этот код

val bottomNav = activity?.findViewById<BottomNavigationView>(R.id.activity_main_bottom_navigation)
    bottomNav?.selectedItemId = R.id.the_id_of_the_icon__that_represent_the_fragment
1
Declan Nnadozie

Попробуй это.

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {

            // Gets the previous global stack count
            int previousStackCount = mPreviousStackCount;

            // Gets a FragmentManager instance
            FragmentManager localFragmentManager = getSupportFragmentManager();

            // Sets the current back stack count
            int currentStackCount = localFragmentManager.getBackStackEntryCount();

            // Re-sets the global stack count to be the current count
            mPreviousStackCount = currentStackCount;

            boolean popping = currentStackCount < previousStackCount;

            if(popping){
                bottomNavigationView.getMenu().getItem(0).setChecked(true);
            }

        }
    });
1
bagyn