studio navegacion inferior developer bottom barra bar android android-fragments android-support-library bottomnavigationview

android - navegacion - Fragmento recreado en el elemento de vista de navegación inferior seleccionado



menu inferior android studio (10)

A continuación se encuentra mi código para el elemento de vista de navegación inferior seleccionado

bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { Fragment fragment = null; switch (item.getItemId()) { case R.id.action_one: // Switch to page one fragment = FragmentA.newInstance(); break; case R.id.action_two: // Switch to page two fragment = FragmentB.newInstance(); break; case R.id.action_three: // Switch to page three fragment = FragmentC.newInstance(); break; } getSupportFragmentManager().beginTransaction().replace(R.id.container,fragment,"TAG").commit(); return true; } });

Ahora, mi problema es que cada vez que se vuelve a crear un fragmento y no quiero que se vuelva a crear un fragmento cada vez que también intenté agregar addToBackStack (nulo), pero en este caso, al presionar el botón Atrás, sigue apareciendo fragmentos de la pila que no quiero.

¿Hay alguna forma de mostrar los fragmentos en la barra de navegación inferior seleccionada sin volver a crear el fragmento?


Con la biblioteca de soporte v26 puedes hacer esto

FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); Fragment curFrag = mFragmentManager.getPrimaryNavigationFragment(); if (curFrag != null) { fragmentTransaction.detach(curFrag); } Fragment fragment = mFragmentManager.findFragmentByTag(tag); if (fragment == null) { fragment = new YourFragment(); fragmentTransaction.add(container.getId(), fragment, tag); } else { fragmentTransaction.attach(fragment); } fragmentTransaction.setPrimaryNavigationFragment(fragment); fragmentTransaction.setReorderingAllowed(true); fragmentTransaction.commitNowAllowingStateLoss();


Esto pareció funcionar bien para mí. En lugar de adjuntar y separar, uso mostrar u ocultar para mantener el estado del fragmento.

public void changeFragment(Fragment fragment, String tagFragmentName) { FragmentManager mFragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); Fragment currentFragment = mFragmentManager.getPrimaryNavigationFragment(); if (currentFragment != null) { fragmentTransaction.hide(currentFragment); } Fragment fragmentTemp = mFragmentManager.findFragmentByTag(tagFragmentName); if (fragmentTemp == null) { fragmentTemp = fragment; fragmentTransaction.add(R.id.frame_layout, fragmentTemp, tagFragmentName); } else { fragmentTransaction.show(fragmentTemp); } fragmentTransaction.setPrimaryNavigationFragment(fragmentTemp); fragmentTransaction.setReorderingAllowed(true); fragmentTransaction.commitNowAllowingStateLoss(); }

Y así es como lo uso.

private void initViews() { BottomNavigationView bottomNavigationView = findViewById(R.id.navigation); bottomNavigationView.setOnNavigationItemSelectedListener (new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { Fragment selectedFragment = null; switch (item.getItemId()) { case R.id.explore: changeFragment(new ExploreFragment(), ExploreFragment.class .getSimpleName()); toggleViews(true, ""); break; case R.id.favorite: changeFragment(new FavoriteFragment(), FavoriteFragment.class .getSimpleName()); toggleViews(false, "Favorites"); break; case R.id.venue: changeFragment(new VenueFragment(), VenueFragment.class.getSimpleName()); toggleViews(false, "Venues"); break; case R.id.profile: changeFragment(new ProfileFragment(), ProfileFragment.class .getSimpleName()); toggleViews(false, "Profile"); break; } return true; } }); //Manually displaying the first fragment - one time only changeFragment(new ExploreFragment(), ExploreFragment.class .getSimpleName()); }


Hay varios casos de prueba involucrados en la navegación correcta. Estoy pegando mi código con todos los casos de prueba seleccionados.

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); switch (item.getItemId()) { case R.id.dashboard: Fragment fragment; fragment = fragmentManager.findFragmentByTag(DashboardFragment.TAG); if (fragment == null) { fragment = new DashboardFragment(); fragmentTransaction.add(R.id.frame, fragment, DashboardFragment.TAG); } else { fragmentTransaction.detach(fragmentManager.getPrimaryNavigationFragment()); fragmentTransaction.attach(fragment); } fragmentTransaction.setPrimaryNavigationFragment(fragment); fragmentTransaction.commitNow(); return true; case R.id.expenses: fragment = fragmentManager.findFragmentByTag(ExpenseFragment.TAG); if (fragment == null) { fragment = new ExpenseFragment(); fragmentTransaction.add(R.id.frame, fragment, ExpenseFragment.TAG); } else { fragmentTransaction.detach(fragmentManager.getPrimaryNavigationFragment()); fragmentTransaction.attach(fragment); } fragmentTransaction.setPrimaryNavigationFragment(fragment); fragmentTransaction.commitNow(); return true; case R.id.vehicle_parts: Bundle bundle = new Bundle(); bundle.putInt("odometer", vehicle.getOdometer()); bundle.putString("vehicle_id", vehicle.get_id()); fragment = fragmentManager.findFragmentByTag(PartsFragment.TAG); if (fragment == null) { fragment = new PartsFragment(); fragment.setArguments(bundle); fragmentTransaction.add(R.id.frame, fragment, PartsFragment.TAG); } else { fragmentTransaction.detach(fragmentManager.getPrimaryNavigationFragment()); fragmentTransaction.attach(fragment); } fragmentTransaction.setPrimaryNavigationFragment(fragment); fragmentTransaction.commitNow(); return true; case R.id.blog: fragment = fragmentManager.findFragmentByTag(BlogFragment.TAG); if (fragment == null) { fragment = new BlogFragment(); fragmentTransaction.add(R.id.frame, fragment, BlogFragment.TAG); } else { fragmentTransaction.detach(fragmentManager.getPrimaryNavigationFragment()); fragmentTransaction.attach(fragment); } fragmentTransaction.setPrimaryNavigationFragment(fragment); fragmentTransaction.commitNow(); return true; } return false;


He mejorado las respuestas de @Viven y lo he escrito con Kotlin. Mi versión crea una instancia del fragmento solo por primera vez, oculta / muestra. Soy nuevo en Kotlin, así que dime si puedo mejorar algo.

Necesitamos mantener una identificación para etiquetar el mapa:

private val fragmentTags = hashMapOf( R.id.action_home to "home_fragment", R.id.action_profile to "profile_fragment" )

El código del oyente:

bottomNavigation.run { setOnNavigationItemSelectedListener { menuItem -> supportFragmentManager.beginTransaction() .let { transaction -> // hide current fragment supportFragmentManager.primaryNavigationFragment?.let { // if selected fragment''s tag is same, do nothing. if (it.tag == fragmentTags[menuItem.itemId]) { return@setOnNavigationItemSelectedListener true } transaction.hide(it) } var fragment = supportFragmentManager.findFragmentByTag(fragmentTags[menuItem.itemId]) if (fragment == null) { // instantiate fragment for the first time fragment = when(menuItem.itemId) { R.id.action_home -> HomeFragment() R.id.action_profile -> ProfileFragment() else -> null }?.also { // and add it transaction.add(R.id.frame, it, fragmentTags[menuItem.itemId]) } } else { // if it''s found show it transaction.show(fragment) } transaction .setPrimaryNavigationFragment(fragment) .setReorderingAllowed(true) }.commitNowAllowingStateLoss() return@setOnNavigationItemSelectedListener true } //bottomNavigation things itemIconTintList = null selectedItemId = R.id.action_home }


Me enfrenté al mismo problema y, finalmente, encontré la solución, puede probar este código. es un trabajo para mi

import android.support.annotation.NonNull; import android.support.design.widget.BottomNavigationView; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MenuItem; import android.widget.FrameLayout; import android.widget.Toast; public class MainActivity extends AppCompatActivity { public BottomNavigationView bv; public home_fragment home; public account_fragment afrag; public other_fragment other; public FrameLayout fr; android.support.v4.app.Fragment current; //public FragmentTransaction frt; public static int temp=0; final Fragment fragment11 = new account_fragment(); final Fragment fragment22 = new home_fragment(); final Fragment fragment33 = new other_fragment(); final FragmentManager fm = getSupportFragmentManager(); Fragment active = fragment11; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bv=(BottomNavigationView) findViewById(R.id.navigationView); fm.beginTransaction().add(R.id.main_frame, fragment33, "3").hide(fragment33).commit(); fm.beginTransaction().add(R.id.main_frame, fragment22, "2").hide(fragment22).commit(); fm.beginTransaction().add(R.id.main_frame,fragment11, "1").commit(); bv.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.account: fm.beginTransaction().hide(active).show(fragment11).commit(); active = fragment11; return true; case R.id.home1: fm.beginTransaction().hide(active).show(fragment22).commit(); active = fragment22; return true; case R.id.other: fm.beginTransaction().hide(active).show(fragment33).commit(); active = fragment33; return true; } return false; } }); bv.setOnNavigationItemReselectedListener(new BottomNavigationView.OnNavigationItemReselectedListener() { @Override public void onNavigationItemReselected(@NonNull MenuItem item) { Toast.makeText(MainActivity.this, "Reselected", Toast.LENGTH_SHORT).show(); } }); } }


Prueba esto :

bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { Fragment fragment = null; Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.container); switch (item.getItemId()) { case R.id.action_one: // Switch to page one if (!(currentFragment instanceof FragmentA)) { fragment = FragmentA.newInstance(); } break; case R.id.action_two: // Switch to page two if (!(currentFragment instanceof FragmentB)) { fragment = FragmentB.newInstance(); } break; case R.id.action_three: // Switch to page three if (!(currentFragment instanceof FragmentC)) { fragment = FragmentC.newInstance(); } break; } getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "TAG").commit(); return true; } });

Obtendrá el fragmento actual en su container y, si vuelve a hacer clic en este fragmento, no volverá a agregar el fragmento.


Tenga cuidado al usar replace . Incluso si se proporciona un fragmento que ya existe en la memoria, el replace reiniciará el ciclo de vida del fragmento. Para evitar un reinicio, los métodos del objeto de transacción incluyen add , show y hide , que se pueden usar para mostrar el fragmento correcto sin reiniciarlo.

private fun switchFragment(index: Int) { val transaction = supportFragmentManager.beginTransaction() val tag = fragments[index].tag // if the fragment has not yet been added to the container, add it first if (supportFragmentManager.findFragmentByTag(tag) == null) { transaction.add(R.id.container, fragments[index], tag) } transaction.hide(fragments[navigationBar.currentTabPosition]) transaction.show(fragments[index]) transaction.commit() }


Use setOnNavigationItemReselectedListener de esta manera:

private BottomNavigationView.OnNavigationItemReselectedListener onNavigationItemReselectedListener = new BottomNavigationView.OnNavigationItemReselectedListener() { @Override public void onNavigationItemReselected(@NonNull MenuItem item) { Toast.makeText(MainActivity.this, "Reselected", Toast.LENGTH_SHORT).show(); } };

y llámalo usando:

navigation.setOnNavigationItemReselectedListener(onNavigationItemReselectedListener);


setOnNavigationItemReselectedListener sería una mejor solución para eso


ViewPager este problema agregando un ViewPager al que ViewPager todos mis fragmentos de navegación. Su adaptador ( FragmentPagerAdapter ) no recrea las instancias de fragmentos cuando el usuario navega a través de BotoomNavigationView .

Para lograr esto, tienes que completar 5 sencillos pasos:

  1. agrega un ViewPager a tu diseño;
  2. implementar su adaptador:

    class YourNavigationViewPagerAdapter(fm: FragmentManager, private val param1: Int, private val param2: Int) : FragmentPagerAdapter(fm) { override fun getItem(p0: Int) = when(p0) { 0 -> NavigationFragment1.newInstance(param1, param2) 1 -> NavigationFragment2.newInstance(param1, param2) 2 -> NavigationFragment3.newInstance(param1, param2) else -> null } override fun getCount() = 3 }

  3. No te olvides de configurar el nuevo adaptador:

    yourViewPager.adapter = YourNavigationViewPagerAdapter(supportFragmentManager, param1, param2)

  4. establezca un OnNavigationItemSelectedListener en su BottomNavigationView como lo siguiente:

    yourBottomNavigationView.setOnNavigationItemSelectedListener { when(it.itemId) { R.id.yourFirstFragmentMenuItem -> { yourViewPager.currentItem = 0 true } R.id.yourSecondFragmentMenuItem -> { yourViewPager.currentItem = 1 true } R.id.yourThirdFragmentMenuItem -> { yourViewPager.currentItem = 2 true } else -> false } }

  5. establezca un OnPageChangeListener para su ViewPager como lo siguiente:

    yourViewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { override fun onPageScrollStateChanged(p0: Int) { } override fun onPageScrolled(p0: Int, p1: Float, p2: Int) { } override fun onPageSelected(p0: Int) { yourBottomNavigationView.menu.getItem(p0).isChecked = true } })

  6. disfrutar :)