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:
- agrega un
ViewPager
a tu diseño; 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 }
No te olvides de configurar el nuevo adaptador:
yourViewPager.adapter = YourNavigationViewPagerAdapter(supportFragmentManager, param1, param2)
establezca un
OnNavigationItemSelectedListener
en suBottomNavigationView
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 } }
establezca un
OnPageChangeListener
para suViewPager
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 } })
disfrutar :)