studio regresar programar programacion navegar llamar fragments entre desde boton atras anterior adelante activity android android-fragments

programar - regresar a un activity anterior android



Presión del botón Atrás del fragmento de Android (25)

Esta pregunta ya tiene una respuesta aquí:

Tengo algunos fragmentos en mi actividad.

[1], [2], [3], [4], [5], [6]

Y en el botón Atrás Presione I debe regresar de [2] a [1] si el fragmento activo actual es [2], o no hacer nada de lo contrario.

¿Cuál es la mejor práctica para hacer eso?

EDITAR : la aplicación no debe regresar a [2] desde [3] ... [6]


Comprobando el backstack funciona perfectamente

@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if (getFragmentManager().getBackStackEntryCount() == 1) { // DO something here since there is only one fragment left // Popping a dialog asking to quit the application return false; } } return super.onKeyDown(keyCode, event); }


Agregue addToBackStack () para fragmentar la transacción y luego use el siguiente código para Implementar la Navegación Atrás para Fragmentos

getSupportFragmentManager().addOnBackStackChangedListener( new FragmentManager.OnBackStackChangedListener() { public void onBackStackChanged() { // Update your UI here. } });


Agregue este código en su actividad

@Anular

public void onBackPressed() { if (getFragmentManager().getBackStackEntryCount() == 0) { super.onBackPressed(); } else { getFragmentManager().popBackStack(); } }

Y agrega esta línea en tu Fragmento antes de commit ()

ft.addToBackStack ("Cualquier nombre");


Código de trabajo:

package com.example.keralapolice; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentManager.OnBackStackChangedListener; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; public class ChiefFragment extends Fragment { View view; // public OnBackPressedListener onBackPressedListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle args) { view = inflater.inflate(R.layout.activity_chief, container, false); getActivity().getActionBar().hide(); view.setFocusableInTouchMode(true); view.requestFocus(); view.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { Log.i(getTag(), "keyCode: " + keyCode); if (keyCode == KeyEvent.KEYCODE_BACK) { getActivity().getActionBar().show(); Log.i(getTag(), "onKey Back listener is working!!!"); getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); // String cameback="CameBack"; Intent i = new Intent(getActivity(), home.class); // i.putExtra("Comingback", cameback); startActivity(i); return true; } else { return false; } } }); return view; } }


Creamos una pequeña biblioteca para manejar la prensa inversa en múltiples fragmentos y / o en la Actividad. El uso es tan simple como agregar dependencia en su archivo de gradle:

compile ''net.skoumal.fragmentback:fragment-back:0.1.0''

Deje que su fragmento implemente la interfaz BackFragment :

public abstract class MyFragment extends Fragment implements BackFragment { public boolean onBackPressed() { // -- your code -- // return true if you want to consume back-pressed event return false; } public int getBackPriority() { return NORMAL_BACK_PRIORITY; } }

Notifique a sus fragmentos sobre las prensas de espalda:

public class MainActivity extends AppCompatActivity { @Override public void onBackPressed() { // first ask your fragments to handle back-pressed event if(!BackFragmentHelper.fireOnBackPressedEvent(this)) { // lets do the default back action if fragments don''t consume it super.onBackPressed(); } } }

Para más detalles y otros casos de uso, visite la página de GitHub:

https://github.com/skoumalcz/fragment-back


Crear interfaces:

BackButtonHandlerInterface

public interface BackButtonHandlerInterface { void addBackClickListener (OnBackClickListener onBackClickListener); void removeBackClickListener (OnBackClickListener onBackClickListener); }

OnBackClickListener

public interface OnBackClickListener { boolean onBackClick(); }

En Actividad:

public class MainActivity extends AppCompatActivity implements BackButtonHandlerInterface { private ArrayList<WeakReference<OnBackClickListener>> backClickListenersList = new ArrayList<>(); @Override public void addBackClickListener(OnBackClickListener onBackClickListener) { backClickListenersList.add(new WeakReference<>(onBackClickListener)); } @Override public void removeBackClickListener(OnBackClickListener onBackClickListener) { for (Iterator<WeakReference<OnBackClickListener>> iterator = backClickListenersList.iterator(); iterator.hasNext();){ WeakReference<OnBackClickListener> weakRef = iterator.next(); if (weakRef.get() == onBackClickListener){ iterator.remove(); } } } @Override public void onBackPressed() { if(!fragmentsBackKeyIntercept()){ super.onBackPressed(); } } private boolean fragmentsBackKeyIntercept() { boolean isIntercept = false; for (WeakReference<OnBackClickListener> weakRef : backClickListenersList) { OnBackClickListener onBackClickListener = weakRef.get(); if (onBackClickListener != null) { boolean isFragmIntercept = onBackClickListener.onBackClick(); if (!isIntercept) isIntercept = isFragmIntercept; } } return isIntercept; } }

En Fragmento :

public class MyFragment extends Fragment implements OnBackClickListener{ private BackButtonHandlerInterface backButtonHandler; @Override public void onAttach(Activity activity) { super.onAttach(activity); backButtonHandler = (BackButtonHandlerInterface) activity; backButtonHandler.addBackClickListener(this); } @Override public void onDetach() { super.onDetach(); backButtonHandler.removeBackClickListener(this); backButtonHandler = null; } @Override public boolean onBackClick() { //This method handle onBackPressed()! return true or false return false; } }


Creo que la forma más fácil es crear una interfaz, y en la actividad comprobar si el fragmento es del tipo de interfaz, y si es así, llame a su método para controlar el pop. Aquí está la interfaz para implementar en el fragmento.

public interface BackPressedFragment { // Note for this to work, name AND tag must be set anytime the fragment is added to back stack, e.g. // getActivity().getSupportFragmentManager().beginTransaction() // .replace(R.id.fragment_container, MyFragment.newInstance(), "MY_FRAG_TAG") // .addToBackStack("MY_FRAG_TAG") // .commit(); // This is really an override. Should call popBackStack itself. void onPopBackStack(); }

Aquí es cómo implementarlo.

public class MyFragment extends Fragment implements BackPressedFragment @Override public void onPopBackStack() { /* Your code goes here, do anything you want. */ getActivity().getSupportFragmentManager().popBackStack(); }

Y en su actividad, cuando maneje el pop (probablemente tanto en onBackPressed como en onOptionsItemSelected), haga estallar el backstack usando este método:

public void popBackStack() { FragmentManager fm = getSupportFragmentManager(); // Call current fragment''s onPopBackStack if it has one. String fragmentTag = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName(); Fragment currentFragment = getSupportFragmentManager().findFragmentByTag(fragmentTag); if (currentFragment instanceof BackPressedFragment) ((BackPressedFragment)currentFragment).onPopBackStack(); else fm.popBackStack(); }


Cuando addToBackStack() transición entre Fragmentos, llame a addToBackStack() como parte de su FragmentTransaction :

FragmentTransaction tx = fragmentManager.beginTransation(); tx.replace( R.id.fragment, new MyFragment() ).addToBackStack( "tag" ).commit();

Si necesita un control más detallado (es decir, cuando algunos Fragmentos están visibles, desea suprimir la tecla de retroceso) puede establecer un OnKeyListener en la vista principal de su fragmento:

//You need to add the following line for this solution to work; thanks skayred fragment.getView().setFocusableInTouchMode(true); fragment.getView().requestFocus(); fragment.getView().setOnKeyListener( new OnKeyListener() { @Override public boolean onKey( View v, int keyCode, KeyEvent event ) { if( keyCode == KeyEvent.KEYCODE_BACK ) { return true; } return false; } } );


Después de ver todas las soluciones, me di cuenta de que hay una solución mucho más simple.

En el onBackPressed () de su actividad que aloja todos sus fragmentos, encuentre el fragmento que desea evitar. Entonces si lo encuentran, solo regresen. Entonces popBackStack nunca sucederá para este fragmento.

@Override public void onBackPressed() { Fragment1 fragment1 = (Fragment1) getFragmentManager().findFragmentByTag(“Fragment1”); if (fragment1 != null) return; if (getFragmentManager().getBackStackEntryCount() > 0){ getFragmentManager().popBackStack(); } }


En su método oncreateView () necesita escribir este código y en la condición KEYCODE_BACk puede escribir cualquiera que sea la funcionalidad que desee

View v = inflater.inflate(R.layout.xyz, container, false); //Back pressed Logic for fragment v.setFocusableInTouchMode(true); v.requestFocus(); v.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { if (keyCode == KeyEvent.KEYCODE_BACK) { getActivity().finish(); Intent intent = new Intent(getActivity(), MainActivity.class); startActivity(intent); return true; } } return false; } });


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 utilizando el patrón de estrategia.

Para algunos de ustedes, quizás 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; } }


Estoy trabajando con SlidingMenu y Fragmento, presente mi caso aquí y espero que ayude a alguien.

Lógica cuando se presiona la tecla [Atrás]:

  1. Cuando SlidingMenu muestre, ciérralo, no hay más cosas que hacer.
  2. O cuando se muestre el segundo (o más) Fragmento, vuelva al Fragmento anterior y no tendrá que hacer nada más.
  3. SlidingMenu no se muestra, el Fragmento actual es # 0, haga la tecla [Atrás] original.

    public class Main extends SherlockFragmentActivity { private SlidingMenu menu=null; Constants.VP=new ViewPager(this); //Some stuff... @Override public void onBackPressed() { if(menu.isMenuShowing()) { menu.showContent(true); //Close SlidingMenu when menu showing return; } else { int page=Constants.VP.getCurrentItem(); if(page>0) { Constants.VP.setCurrentItem(page-1, true); //Show previous fragment until Fragment#0 return; } else {super.onBackPressed();} //If SlidingMenu is not showing and current Fragment is #0, do the original [Back] key does. In my case is exit from APP } } }


La forma más ideal de hacerlo se encuentra aquí: Fragmento: el cual se invoca cuando se presiona el botón Atrás y se personaliza.

public class MyActivity extends Activity { //... //Defined in Activity class, so override @Override public void onBackPressed() { super.onBackPressed(); myFragment.onBackPressed(); } } public class MyFragment extends Fragment { //Your created method public static void onBackPressed() { //Pop Fragments off backstack and do your other checks } }


O puede usar getSupportFragmentManager().getBackStackEntryCount() para ver qué hacer:

@Override public void onBackPressed() { logger.d("@@@@@@ back stack entry count : " + getSupportFragmentManager().getBackStackEntryCount()); if (getSupportFragmentManager().getBackStackEntryCount() != 0) { // only show dialog while there''s back stack entry dialog.show(getSupportFragmentManager(), "ConfirmDialogFragment"); } else if (getSupportFragmentManager().getBackStackEntryCount() == 0) { // or just go back to main activity super.onBackPressed(); } }


Para aquellos que usan fragmentos estáticos

En el caso de que tenga un fragmento estático, sería preferible. Crea un objeto de instancia de tu fragmento.

private static MyFragment instance=null;

en onCreate () de MyFragment inicialice esa instancia

instance=this;

También hacer una función para obtener instancia.

public static MyFragment getInstance(){ return instance; }

tambien hacen funciones

public boolean allowBackPressed(){ if(allowBack==true){ return true; } return false; } //allowBack is a boolean variable that will be set to true at the action //where you want that your backButton should not close activity. In my case I open //Navigation Drawer then I set it to true. so when I press backbutton my //drawer should be get closed public void performSomeAction(){ //.. Your code ///Here I have closed my drawer }

En tu actividad puedes hacer

@Override public void onBackPressed() { if (MyFragment.getInstance().allowBackPressed()) { MyFragment.getInstance().performSomeAction(); } else{ super.onBackPressed(); } }


Prefiero hacer algo como esto:

private final static String TAG_FRAGMENT = "TAG_FRAGMENT"; private void showFragment() { final Myfragment fragment = new MyFragment(); final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragment, fragment, TAG_FRAGMENT); transaction.addToBackStack(null); transaction.commit(); } @Override public void onBackPressed() { final Myfragment fragment = (Myfragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT); if (fragment.allowBackPressed()) { // and then you define a method allowBackPressed with the logic to allow back pressed or not super.onBackPressed(); } }


Puede usar desde getActionBar().setDisplayHomeAsUpEnabled() :

@Override public void onBackStackChanged() { int backStackEntryCount = getFragmentManager().getBackStackEntryCount(); if(backStackEntryCount > 0){ getActionBar().setDisplayHomeAsUpEnabled(true); }else{ getActionBar().setDisplayHomeAsUpEnabled(false); } }


Si desea manejar el evento de la tecla Atrás del hardware, debe hacerlo siguiendo el código en su método onActivityCreated () de Fragmento.

También debe comprobar el evento Action_Down o Action_UP. Si no lo comprueba, el método onKey () llamará 2 veces.

Además, si su rootview (getView ()) no contendrá el foco, entonces no funcionará. Si ha hecho clic en cualquier control, entonces nuevamente debe concentrarse en rootview usando getView (). RequestFocus (); Después de esto solo llamará onKeydown ().

getView().setFocusableInTouchMode(true); getView().requestFocus(); getView().setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { if (keyCode == KeyEvent.KEYCODE_BACK) { Toast.makeText(getActivity(), "Back Pressed", Toast.LENGTH_SHORT).show(); return true; } } return false; } });

Trabajando muy bien para mi.


Si está utilizando FragmentActivity. entonces haz esto

Primera llamada Esto dentro de tu Fragmento.

public void callParentMethod(){ getActivity().onBackPressed(); }

y luego llame onBackPressed método onBackPressed junto a su clase FragmentActivity primaria.

@Override public void onBackPressed() { //super.onBackPressed(); //create a dialog to ask yes no question whether or not the user wants to exit ... }


Si gestiona el flujo de agregar a la pila trasera cada transacción, entonces puede hacer algo como esto para mostrar el fragmento anterior cuando el usuario presiona el botón Atrás (también puede asignar el botón de inicio).

@Override public void onBackPressed() { if (getFragmentManager().getBackStackEntryCount() > 0) getFragmentManager().popBackStack(); else super.onBackPressed(); }


Use el método addToBackStack cuando reemplace un fragmento por otro:

getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).addToBackStack("my_fragment").commit();

Luego, en su actividad, use el siguiente código para volver de un fragmento a otro (el anterior).

@Override public void onBackPressed() { if (getFragmentManager().getBackStackEntryCount() > 0) { getFragmentManager().popBackStack(); } else { super.onBackPressed(); } }


en la clase de fragmento poner este código para el evento de vuelta:

rootView.setFocusableInTouchMode(true); rootView.requestFocus(); rootView.setOnKeyListener( new OnKeyListener() { @Override public boolean onKey( View v, int keyCode, KeyEvent event ) { if( keyCode == KeyEvent.KEYCODE_BACK ) { FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.frame_container, new Book_service_provider()).commit(); return true; } return false; } } );


si superas el método onKey para la vista de fragmentos necesitarás:

view.setFocusableInTouchMode(true); view.requestFocus(); view.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { Log.i(tag, "keyCode: " + keyCode); if( keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { Log.i(tag, "onKey Back listener is working!!!"); getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); return true; } return false; } });


@Override public void onResume() { super.onResume(); getView().setFocusableInTouchMode(true); getView().requestFocus(); getView().setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){ if (mDrawerLayout.isDrawerOpen(GravityCompat.START)){ mDrawerLayout.closeDrawer(GravityCompat.START); } return true; } return false; } }); }


rootView.setFocusableInTouchMode(true); rootView.requestFocus(); rootView.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { Fragment NameofFragment = new NameofFragment; FragmentTransaction transaction=getFragmentManager().beginTransaction(); transaction.replace(R.id.frame_container,NameofFragment); transaction.commit(); return true; } return false; } }); return rootView;