Tengo un pestañas actionbar / ViewPager diseño con tres pestañas dicen A , B , y C . En la ficha C pestaña (fragmento), añado otro fragmento digamos fragmento D . con
DFragment f= new DFragment();
ft.add(android.R.id.content, f, "");
ft.remove(CFragment.this);
ft.addToBackStack(null);
ft.commit();
Modifico la barra de acción en onResume de DFragment para agregar el botón:
ActionBar ab = getActivity().getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);
Ahora, en DFragment, cuando presiono el botón Atrás del hardware (teléfono), regreso al diseño original con pestañas (ABC) con CFragment seleccionado. ¿Cómo puedo lograr esta funcionalidad con el botón arriba de la barra de acciones?
android
android-fragments
android-actionbar
SohailAziz
fuente
fuente
Respuestas:
Implemente
OnBackStackChangedListener
y agregue este código a su actividad de fragmentos.@Override public void onCreate(Bundle savedInstanceState) { //Listen for changes in the back stack getSupportFragmentManager().addOnBackStackChangedListener(this); //Handle when activity is recreated like on orientation Change shouldDisplayHomeUp(); } @Override public void onBackStackChanged() { shouldDisplayHomeUp(); } public void shouldDisplayHomeUp(){ //Enable Up button only if there are entries in the back stack boolean canGoBack = getSupportFragmentManager().getBackStackEntryCount()>0; getSupportActionBar().setDisplayHomeAsUpEnabled(canGoBack); } @Override public boolean onSupportNavigateUp() { //This method is called when the up button is pressed. Just the pop back stack. getSupportFragmentManager().popBackStack(); return true; }
fuente
onSupportNavigateUp()
, "El método no anula el método de su superclase".onOptionsItemSelected
, también es posible verificar el itemId enandroid.R.id.home
lugar de agregaronSupportNavigateUp
.ActionBar
? No veo uno cuando implemento este código. Solo puedo hacer clic en el icono, pero no hace nada. Android 4.0 o superior.Lo tengo. simplemente anule onOptionsItemSelected en la actividad de alojamiento y muestre el backstack, por ejemplo
public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: { FragmentManager fm = getSupportFragmentManager(); if (fm.getBackStackEntryCount() > 0) { fm.popBackStack(); return true; } break; } } return super.onOptionsItemSelected(item); }
Llame
getActionBar().setDisplayHomeAsUpEnabled(boolean);
ygetActionBar().setHomeButtonEnabled(boolean);
entreonBackStackChanged()
como se explica en una respuesta a continuación.fuente
switch
declaración con el casoandroid.R.id.home
.Si tiene una actividad principal y desea que este botón de arriba funcione como botón de retroceso, puede usar este código:
agregue esto a onCreate en su clase de actividad principal
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { int stackHeight = getSupportFragmentManager().getBackStackEntryCount(); if (stackHeight > 0) { // if we have something on the stack (doesn't include the current shown fragment) getSupportActionBar().setHomeButtonEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } else { getSupportActionBar().setDisplayHomeAsUpEnabled(false); getSupportActionBar().setHomeButtonEnabled(false); } } });
y luego agregue onOptionsItemSelected así:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: getSupportFragmentManager().popBackStack(); return true; .... }
Generalmente uso esto todo el tiempo y parece bastante legítimo.
fuente
Activity
de los míos, con la esperanza de que volviera al fragmento desde el que comenzó. El botón de retroceso aparece cerca del ícono de mi aplicación cuando voy a miActivity
, pero hago clic en el ícono y no pasa nada (debería volver al fragmento). ¿Alguna idea de por qué? Gracias.puedes volver con el botón arriba como el botón atrás;
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: super.onBackPressed(); return true; } return super.onOptionsItemSelected(item); }
fuente
Sé que esta pregunta es antigua, pero es posible que alguien (como yo) también la necesite.
Si su actividad extiende AppCompatActivity , puede usar una solución más simple (dos pasos):
1 - Siempre que agregue un fragmento que no sea de inicio, simplemente muestre el botón arriba, justo después de realizar la transacción del fragmento. Me gusta esto:
// ... add a fragment // Commit the transaction transaction.commit(); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
2 - Luego, cuando se presiona el botón ARRIBA, lo oculta.
@Override public boolean onSupportNavigateUp() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); return true; }
Eso es.
fuente
Usé una combinación de las respuestas de Roger Garzon Nieto y sohailaziz . Mi aplicación tiene una sola MainActivity y fragmentos A, B, C que se cargan en ella. Mi fragmento de "casa" (A) implementa OnBackStackChangedListener y comprueba el tamaño de la backStack; si es menos de uno, oculta el botón ARRIBA. Los fragmentos B y C siempre cargan el botón de retroceso (en mi diseño, B se inicia desde A y C se inicia desde B). La MainActivity en sí misma simplemente abre el backstack al tocar el botón ARRIBA, y tiene métodos para mostrar / ocultar el botón, que los fragmentos llaman:
Actividad principal:
public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // Respond to the action bar's Up/Home button case android.R.id.home: getSupportFragmentManager().popBackStack(); return true; } return super.onOptionsItemSelected(item); } public void showUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(true); } public void hideUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); }
fragmentA (implementa FragmentManager.OnBackStackChangedListener):
public void onCreate(Bundle savedinstanceSate) { // listen to backstack changes getActivity().getSupportFragmentManager().addOnBackStackChangedListener(this); // other fragment init stuff ... } public void onBackStackChanged() { // enable Up button only if there are entries on the backstack if(getActivity().getSupportFragmentManager().getBackStackEntryCount() < 1) { ((MainActivity)getActivity()).hideUpButton(); } }
fragmentoB, fragmentoC:
public void onCreate(Bundle savedinstanceSate) { // show the UP button ((MainActivity)getActivity()).showUpButton(); // other fragment init stuff ... }
fuente
Esto funcionó para mí. Anular onSupportNavigateUp y onBackPressed, por ejemplo (código en Kotlin);
override fun onBackPressed() { val count = supportFragmentManager.backStackEntryCount if (count == 0) { super.onBackPressed() } else { supportFragmentManager.popBackStack() } } override fun onSupportNavigateUp(): Boolean { super.onSupportNavigateUp() onBackPressed() return true }
Ahora en el fragmento, si muestra la flecha hacia arriba
activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
Al hacer clic en él, vuelve a la actividad anterior.
fuente
Kotlin:
class MyActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... supportFragmentManager.addOnBackStackChangedListener { setupHomeAsUp() } setupHomeAsUp() } private fun setupHomeAsUp() { val shouldShow = 0 < supportFragmentManager.backStackEntryCount supportActionBar?.setDisplayHomeAsUpEnabled(shouldShow) } override fun onSupportNavigateUp(): Boolean = supportFragmentManager.popBackStack().run { true } ... }
fuente
Esta es una solución muy buena y confiable: http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments/
El tipo ha creado un fragmento abstracto que maneja el comportamiento de backPress y está cambiando entre los fragmentos activos usando el patrón de estrategia.
Para algunos de ustedes, tal vez haya un pequeño inconveniente en la clase abstracta ...
En breve, la solución del enlace es la siguiente:
// Abstract Fragment handling the back presses public abstract class BackHandledFragment extends Fragment { protected BackHandlerInterface backHandlerInterface; public abstract String getTagText(); public abstract boolean onBackPressed(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(!(getActivity() instanceof BackHandlerInterface)) { throw new ClassCastException("Hosting activity must implement BackHandlerInterface"); } else { backHandlerInterface = (BackHandlerInterface) getActivity(); } } @Override public void onStart() { super.onStart(); // Mark this fragment as the selected Fragment. backHandlerInterface.setSelectedFragment(this); } public interface BackHandlerInterface { public void setSelectedFragment(BackHandledFragment backHandledFragment); } }
Y uso en la actividad:
// BASIC ACTIVITY CODE THAT LETS ITS FRAGMENT UTILIZE onBackPress EVENTS // IN AN ADAPTIVE AND ORGANIZED PATTERN USING BackHandledFragment public class TheActivity extends FragmentActivity implements BackHandlerInterface { private BackHandledFragment selectedFragment; @Override public void onBackPressed() { if(selectedFragment == null || !selectedFragment.onBackPressed()) { // Selected fragment did not consume the back press event. super.onBackPressed(); } } @Override public void setSelectedFragment(BackHandledFragment selectedFragment) { this.selectedFragment = selectedFragment; } }
fuente