¿Hay alguna manera de implementar onBackPressed()
en Android Fragment similar a la implementación en Android Activity?
Como el ciclo de vida del fragmento no tiene onBackPressed()
. ¿Existe algún otro método alternativo para anular los onBackPressed()
fragmentos de Android 3.0?
android
android-fragments
onbackpressed
Android_programmer_camera
fuente
fuente
Respuestas:
Resolví de esta manera anular
onBackPressed
en la Actividad. Todos losFragmentTransaction
sonaddToBackStack
antes de comprometerse:fuente
En mi opinión, la mejor solución es:
SOLUCIÓN JAVA
Crear interfaz simple:
Y en tu actividad
Finalmente en tu Fragmento:
SOLUCIÓN KOTLIN
1 - Crear interfaz
2 - Prepara tu actividad
3 - Implementar en tu Fragmento objetivo
fuente
R.id.main_container
? ¿Es esa la identificación para el FragmentPager?.?
) y forzar no nulos (!!
) puede generar NPE: el reparto no siempre es seguro. Prefiero escribirif ((fragment as? IOnBackPressed)?.onBackPressed()?.not() == true) { ... }
o más kotliney(fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let { ... }
.onBackPressed()?.takeIf { !it }?.let{...}
?.not()
solo devuelve el inverso.val fragment = this.supportFragmentManager.findFragmentById(R.id.flContainer) as? NavHostFragment val currentFragment = fragment?.childFragmentManager?.fragments?.get(0) as? IOnBackPressed currentFragment?.onBackPressed()?.takeIf { !it }?.let{ super.onBackPressed() }
Esto es para personas que usan Kotlin y NavigationControllerDe acuerdo con @HaMMeRed, la respuesta aquí es pseudocódigo cómo debería funcionar. Digamos que su actividad principal se llama
BaseActivity
que tiene fragmentos secundarios (como en el ejemplo de SlidingMenu lib). Aquí están los pasos:Primero necesitamos crear una interfaz y una clase que implemente su interfaz para tener un método genérico
Crear interfaz de clase
OnBackPressedListener
Crear clase que implemente habilidades de
OnBackPressedListener
Desde ahora, trabajaremos en nuestro código
BaseActivity
y sus fragmentos.Crea un oyente privado en la cima de tu clase
BaseActivity
crear un método para configurar el oyente en
BaseActivity
en anulación
onBackPressed
implementar algo asíen su fragmento en
onCreateView
usted debe agregar nuestro oyenteVoila, ahora cuando haces clic de nuevo en el fragmento, debes capturar tu método personalizado de respaldo.
fuente
onBackPressed()
qué fragmento se estaba mostrando cuando se presionó el botón Atrás?((BaseActivity)activity).setOnBackPressedListener(new OnBackpressedListener(){ public void doBack() { //...your stuff here }});
Esto funcionó para mí: https://stackoverflow.com/a/27145007/3934111
fuente
Si quisieras ese tipo de funcionalidad, deberías anularla en tu actividad y luego agregar una
YourBackPressed
interfaz a todos tus fragmentos, que invocas en el fragmento relevante cada vez que presionas el botón Atrás.Editar: me gustaría agregar mi respuesta anterior.
Si tuviera que hacer esto hoy, usaría una transmisión, o posiblemente una transmisión ordenada si esperaba que otros paneles se actualicen al unísono al panel de contenido principal / principal.
LocalBroadcastManager
en la Biblioteca de soporte puede ayudar con esto, y usted simplemente envía la transmisiónonBackPressed
y se suscribe en sus fragmentos que les importa. Creo que la mensajería es una implementación más desacoplada y se escalaría mejor, por lo que sería mi recomendación oficial de implementación ahora. Simplemente use laIntent
acción de 's como filtro para su mensaje. envíe su recién creadoACTION_BACK_PRESSED
, envíelo desde su actividad y escúchelo en los fragmentos relevantes.fuente
LocalBroadcastManager
no se pueden hacer transmisiones ordenadasNada de eso es fácil de implementar ni funcionará de manera óptima.
Los fragmentos tienen un método llamado onDetach que hará el trabajo.
ESTO HARÁ EL TRABAJO.
fuente
isRemoving()
como se describe en stackoverflow.com/a/27103891/2914140 .Si está utilizando
androidx.appcompat:appcompat:1.1.0
o superior, puede agregar unOnBackPressedCallback
fragmento a su fragmento de la siguiente maneraVer https://developer.android.com/guide/navigation/navigation-custom-back
fuente
androidx-core-ktx
, puede usarrequireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { /* code to be executed when back is pressed */ }
LifecycleOwner
parámetro debe agregarse como en este ejemplo. Sin él, cualquier fragmento iniciado después llamaráhandleBackPressed()
si se presiona el botón Atrás.Simplemente agregue
addToBackStack
mientras realiza la transición entre sus fragmentos como a continuación:si escribe
addToBackStack(null)
, lo manejará solo, pero si le da una etiqueta, debe manejarlo manualmente.fuente
Como esta pregunta y algunas de las respuestas tienen más de cinco años, permítanme compartir mi solución. Este es un seguimiento y modernización de la respuesta de @oyenigun
ACTUALIZACIÓN: Al final de este artículo, agregué una implementación alternativa usando una extensión de Fragmento abstracto que no involucrará a la Actividad en absoluto, lo que sería útil para cualquier persona con una jerarquía de fragmentos más compleja que involucre fragmentos anidados que requieran un comportamiento de espalda diferente.
Necesitaba implementar esto porque algunos de los fragmentos que uso tienen vistas más pequeñas que me gustaría descartar con el botón Atrás, como pequeñas vistas de información que aparecen, etc., pero esto es bueno para cualquiera que necesite anular el comportamiento de el botón de retroceso dentro de los fragmentos.
Primero, defina una interfaz
Esta interfaz, a la que llamo
Backable
(soy un fanático de las convenciones de nomenclatura), tiene un método únicoonBackPressed()
que debe devolver unboolean
valor. Necesitamos imponer un valor booleano porque necesitaremos saber si presionar el botón Atrás ha "absorbido" el evento Atrás. Devolvertrue
significa que sí, y no se necesita ninguna otra acción, de lo contrario,false
dice que la acción de retroceso predeterminada todavía debe llevarse a cabo. Esta interfaz debe ser su propio archivo (preferiblemente en un paquete separado llamadointerfaces
). Recuerde, separar sus clases en paquetes es una buena práctica.Segundo, encuentra el fragmento superior
Creé un método que devuelve el último
Fragment
objeto en la pila posterior. Yo uso etiquetas ... si usa identificaciones, haga los cambios necesarios. Tengo este método estático en una clase de utilidad que se ocupa de estados de navegación, etc. pero, por supuesto, ponlo donde más te convenga. Para la edificación, he puesto el mío en una clase llamadaNavUtils
.Asegúrese de que el recuento de la pila posterior sea mayor que 0, de lo contrario,
ArrayOutOfBoundsException
podría lanzarse en tiempo de ejecución. Si no es mayor que 0, devuelve nulo. Verificaremos un valor nulo más tarde ...Tercero, implementar en un fragmento
Implemente la
Backable
interfaz en cualquier fragmento donde necesite anular el comportamiento del botón de retroceso. Agregue el método de implementación.En la
onBackPressed()
anulación, ponga cualquier lógica que necesite. Si desea que el botón de nuevo a no saca la pila de vuelta (el comportamiento predeterminado), volverá cierto , que su evento posterior que se haya absorbido. De lo contrario, devuelve falso.Por último, en tu actividad ...
Anule el
onBackPressed()
método y agregue esta lógica:Obtenemos el fragmento actual en la pila posterior, luego hacemos una comprobación nula y determinamos si implementa nuestra
Backable
interfaz. Si es así, determine si el evento fue absorbido. Si es así, hemos terminadoonBackPressed()
y podemos volver. De lo contrario, trátelo como un retroceso normal y llame al método super.Segunda opción para no involucrar a la actividad
A veces, no desea que la Actividad maneje esto en absoluto, y necesita manejarlo directamente dentro del fragmento. Pero, ¿quién dice que no puede tener Fragments con una API de retroceso? Simplemente extienda su fragmento a una nueva clase.
Cree una clase abstracta que extienda Fragment e implemente la
View.OnKeyListner
interfaz ...Como puede ver, cualquier fragmento que se extienda
BackableFragment
capturará automáticamente los clics de regreso utilizando laView.OnKeyListener
interfaz. Simplemente llame alonBackButtonPressed()
método abstracto desde dentro delonKey()
método implementado usando la lógica estándar para discernir la presión de un botón de retroceso. Si necesita registrar clics de teclas que no sean el botón de retroceso, solo asegúrese de llamar alsuper
método al anularonKey()
su fragmento, de lo contrario, anulará el comportamiento en la abstracción.Fácil de usar, solo extienda e implemente:
Dado que el
onBackButtonPressed()
método en la superclase es abstracto, una vez que lo extienda, debe implementarloonBackButtonPressed()
. Regresavoid
porque solo necesita realizar una acción dentro de la clase de fragmento y no necesita retransmitir la absorción de la prensa de nuevo a la Actividad. Asegúrese de llamar alonBackPressed()
método Actividad si lo que está haciendo con el botón Atrás no requiere manejo, de lo contrario, el botón Atrás se desactivará ... ¡y no quiere eso!Advertencias Como puede ver, esto establece al oyente clave en la vista raíz del fragmento, y tendremos que enfocarlo. Si hay textos de edición involucrados (o cualquier otra vista de robo de foco) en su fragmento que extiende esta clase (u otros fragmentos internos o vistas que tengan la misma), deberá manejar eso por separado. Hay un buen artículo sobre cómo extender un EditText para perder el foco en una pulsación hacia atrás.
Espero que alguien encuentre esto útil. Feliz codificación
fuente
super.onBackPressed();
dos veces?currentFragment
. Si el fragmento no es nulo y el fragmento implementa laBackable
interfaz, no se toman medidas. Si el fragmento no es nulo y NO se implementaBackable
, llamamos al método super. Si el fragmento es nulo, salta a la última súper llamada.currentFragment
no sea nulo y sea una instancia de Backable y se separe (presionamos elback
botón y cerramos el fragmento)super.onBackPressed();
se llama la primera aparición de , luego la segunda.La solución es simple:
1) Si tiene una clase de fragmento base que se extienden todos los fragmentos, agregue este código a su clase, de lo contrario, cree una clase de fragmento base
2) En su clase de Actividad, anule onBackPressed de la siguiente manera:
3) En su clase Fragmento, agregue el código deseado:
fuente
onBackPressed()
hacer que el fragmento se desprenda de la actividad.Según la respuesta de @Sterling Diaz, creo que tiene razón. PERO alguna situación estará mal. (ej. Girar pantalla)
Entonces, creo que podríamos detectar si
isRemoving()
alcanzar objetivos.Puedes escribirlo en
onDetach()
oonDestroyView()
. Eso es trabajo.fuente
Bueno, lo hice así, y funcionó para mí.
Interfaz simple
FragmentOnBackClickInterface.java
Implementación de ejemplo
MyFragment.java
luego simplemente anula onBackPressed en actividad
fuente
Debe agregar una interfaz a su proyecto como se muestra a continuación;
Y luego, debe implementar esta interfaz en su fragmento;
Y puede activar este evento onBackPressed en sus actividades en el evento onBackPressed como se muestra a continuación;
fuente
getActivity().onBackPressed();
ya que invocará una excepción: "java.lang.StackOverflowError: tamaño de pila 8MB".Este es solo un pequeño código que hará el truco:
Espero que ayude a alguien :)
fuente
Si usa EventBus, probablemente sea una solución mucho más simple:
y en tu clase de Actividad puedes definir:
BackPressedMessage.java es solo un objeto POJO
Esto es súper limpio y no hay problemas de interfaz / implementación.
fuente
Esta es mi solución:
fuente
Usando el componente de navegación puede hacerlo así :
fuente
¿Qué tal usar onDestroyView ()?
fuente
i = i
oif (1 < 0) {}
.fuente
en su fragmento agregue lo siguiente, no olvide implementar la interfaz de mainactivity.
fuente
En mi solución (Kotlin);
Estoy usando la función onBackAlternative como parámetro en BaseActivity .
BaseActivity
Tengo una función para configurar onBackPressAlternative en BaseFragment .
Fragmento Base
Entonces mi onBackPressAlternative está listo para usar en fragmentos.
Sub Fragmentos
fuente
No implemente el método ft.addToBackStack () para que cuando presione el botón Atrás, su actividad finalice.
fuente
Solo sigue estos pasos:
Siempre al agregar un fragmento,
Luego, en la actividad principal, anular
onBackPressed()
Para manejar el botón de retroceso en su aplicación,
¡Eso es!
fuente
En el ciclo de vida de la actividad, siempre el botón de retroceso de Android se ocupa de las transacciones de FragmentManager cuando usamos FragmentActivity o AppCompatActivity.
Para manejar el backstack no necesitamos manejar su conteo de backstack ni etiquetar nada, pero debemos mantener el enfoque al agregar o reemplazar un fragmento. Encuentre los siguientes fragmentos para manejar los botones de retroceso,
Aquí, no agregaré back stack para mi fragmento de inicio porque es la página de inicio de mi aplicación. Si agrega addToBackStack a HomeFragment, la aplicación esperará para eliminar todo el fragmento en la actividad y luego obtendremos una pantalla en blanco, así que mantengo la siguiente condición,
Ahora, puede ver el fragmento previamente agregado en la actividad y la aplicación se cerrará cuando llegue a HomeFragment. También puede consultar los siguientes fragmentos.
fuente
Fragmento: crea un Fragmento base colocando un método:
Actividad:
Su actividad se ejecutará sobre los fragmentos adjuntos y visibles y llamará a onBackPressed () en cada uno de ellos y cancelará si uno de ellos devuelve 'verdadero' (lo que significa que se ha manejado, por lo que no hay más acciones).
fuente
De acuerdo con las notas de la versión de AndroidX ,
androidx.activity 1.0.0-alpha01
se lanza y presentaComponentActivity
una nueva clase base de las existentesFragmentActivity
yAppCompatActivity
. Y esta versión nos trae una nueva característica:Ahora puede registrar una
OnBackPressedCallback
víaaddOnBackPressedCallback
para recibironBackPressed()
devoluciones de llamada sin necesidad de anular el método en su actividad.fuente
Puede registrar un fragmento en la actividad para manejar la presión posterior:
uso:
En fragmento:
En actividad:
fuente
Proporcionar una navegación hacia atrás personalizada al manejar onBackPressed ahora es más fácil con devoluciones de llamada dentro del fragmento.
Si desea que la acción de retroceso predeterminada se base en alguna condición, puede usar:
fuente
Dentro del método onCreate del fragmento, agregue lo siguiente:
fuente
Mejor solución,
fuente