Fragment androïde poignée Retour bouton appuyer [dupliquer]

cette question a déjà une réponse ici:

j'ai des fragments dans mon activité

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

et sur le bouton de retour appuyer je dois retourner de [2] à [1] si courant actif fragment [2], ou ne rien faire sinon.

Quelle est la meilleure pratique pour le faire?

MODIFIER : l'Application ne doit pas retourner à [2] à partir de [3]...[6]

258
demandé sur zmarties 2011-11-03 12:54:22

25 réponses

lorsque vous êtes en transition entre des Fragments, appelez addToBackStack() dans le cadre de votre FragmentTransaction :

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

si vous avez besoin d'un contrôle plus détaillé (c.-à-d. lorsque certains Fragments sont visibles, vous voulez supprimer la touche back), vous pouvez définir un OnKeyListener sur la vue parent de votre fragment:

//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;
    }
} );
346
répondu Mark Allison 2015-06-11 01:16:32

je préférerais faire quelque chose comme ça:

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();
    }
}
245
répondu saulobrito 2013-01-25 21:46:11

si vous surmontez la méthode onKey pour la vue de fragment, vous aurez besoin de:

    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;
            }
        });
96
répondu ANemati 2017-08-16 19:51:29

utiliser addToBackStack méthode lors du remplacement d'un fragment par un autre:

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

ensuite, dans votre activité, utilisez le code suivant pour revenir d'un fragment à un autre (le précédent).

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}
58
répondu shimatai 2014-10-15 23:00:40

si vous voulez gérer l'événement de retour de clé matériel que vous devez faire en suivant le code dans votre méthode Onactivitycreated() de Fragment.

vous devez également vérifier Action_Down ou l'événement Action_UP. Si vous ne cochez pas, la méthode onKey () appellera 2 fois.

de plus, si votre rootview(getView()) ne contient pas focus, il ne fonctionnera pas. Si vous avez cliqué sur n'importe quel contrôle, vous devez à nouveau vous concentrer sur rootview en utilisant getView ().requestFocus (); après cela seulement onKeydown () appellera.

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;
            }
        });

ça marche très bien pour moi.

42
répondu Tejas Mehta 2014-08-20 05:11:51

la façon la plus idéale de le faire se trouve ici: Fragment: qui callback invoqué lorsque vous appuyez sur le bouton arrière et personnaliser

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
    }
}
23
répondu kakoma 2017-05-23 12:02:56

créer des interfaces:

BackButtonHandlerInterface

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

OnBackClickListener

public interface OnBackClickListener {
     boolean onBackClick();
}

Dans Activité:

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;
    }
}

In Fragment :

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;
    }

}
15
répondu krawa 2017-04-24 11:38:05

 @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;
            }
        });
    }

8
répondu Ranjit Kathiriya 2015-07-07 18:37:23

ou vous pouvez utiliser getSupportFragmentManager().getBackStackEntryCount() pour vérifier ce qu'il faut faire:

@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();
        }
    }
5
répondu Robert 2014-03-04 14:03:23

nous avons créé une bibliothèque minuscule pour manipuler la presse arrière à travers de multiples fragments et/ou en activité. L'utilisation est aussi simple que l'ajout d'une dépendance dans votre fichier gradle:

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

Laissez votre fragment de mettre en œuvre BackFragment de l'interface:

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;
    }
}

informez vos fragments sur les presses arrière:

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();
        }
    }
}

pour plus de détails et d'autres cas d'utilisation visitez la page GitHub:

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

5
répondu gingo 2016-06-17 15:03:49

si vous gérez le flux d'ajout à la pile de retour de chaque transaction, alors vous pouvez faire quelque chose comme cela afin de montrer le fragment précédent lorsque l'utilisateur appuie sur le bouton de retour (vous pouvez mapper le bouton d'accueil aussi).

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0)
        getFragmentManager().popBackStack();
    else
        super.onBackPressed();
}
4
répondu Joaquin Iurchuk 2015-04-27 18:48:00

je travaille avec SlidingMenu et Fragment, je présente mon cas ici et hope aide quelqu'un.

Logique lorsque la touche [Back] est pressée :

  1. quand SlidingMenu montre, fermez - le, plus rien à faire.
  2. ou quand le 2e Fragment(ou plus) apparaît, revenez au Fragment précédent, et plus rien à faire.
  3. SlidingMenu pas de montre, Fragment courant est #0, faire l'original [retour] clé faire.

    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
        }
      }
    }
    
3
répondu RRTW 2013-03-18 09:52:59

c'est une solution très bonne et fiable: http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments /

le gars a fait un fragment abstrait qui gère le comportement de rétraction et passe entre les fragments actifs en utilisant le motif de stratégie.

Pour certains d'entre vous on peut-être un petit inconvénient, dans la classe abstraite...

sous peu, la solution de la link va comme ceci:

// 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);
    }
}   

et usage dans l'activité:

// 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;
    }
}
3
répondu zatziky 2015-01-03 12:06:30

Code De Travail:

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;
    }
}
3
répondu Android 2015-05-14 06:47:05

je pense que la façon la plus facile est de créer une interface, et dans le contrôle D'activité si le fragment est du type d'interface, et si oui, appeler sa méthode pour gérer le pop. Voici l'interface à implémenter dans le fragment.

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();
}

Voici comment l'implémenter.

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

et dans votre activité, lorsque vous manipulez le pop (probablement dans onBackPressed et onOptionsItemSelected), pop the backstack en utilisant cette méthode:

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();
}
3
répondu Matt Koala 2015-10-09 17:53:53
            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;
3
répondu Ashish Soni 2016-03-23 13:00:08

vous pouvez utiliser à partir de getActionBar().setDisplayHomeAsUpEnabled() :

@Override
public void onBackStackChanged() {
    int backStackEntryCount = getFragmentManager().getBackStackEntryCount();

    if(backStackEntryCount > 0){
        getActionBar().setDisplayHomeAsUpEnabled(true);
    }else{
        getActionBar().setDisplayHomeAsUpEnabled(false);
    }
}
2
répondu 2015-04-13 12:29:38

après avoir examiné toutes les solutions, j'ai réalisé qu'il y avait une solution beaucoup plus simple.

dans onBackPressed() de votre activité qui héberge tous vos fragments, trouvez le fragment que vous voulez empêcher la presse arrière. Alors si trouvé, il suffit de revenir. Alors popBackStack n'arrivera jamais pour ce fragment.

  @Override
public void onBackPressed() {

        Fragment1 fragment1 = (Fragment1) getFragmentManager().findFragmentByTag(“Fragment1”);
        if (fragment1 != null)
            return;

        if (getFragmentManager().getBackStackEntryCount() > 0){
            getFragmentManager().popBackStack();

        }
}
2
répondu Harry Aung 2016-03-18 09:54:25

ajouter addToBackStack () à la transaction fragment et ensuite utiliser le code ci-dessous pour implémenter la Navigation arrière pour les Fragments

getSupportFragmentManager().addOnBackStackChangedListener(
    new FragmentManager.OnBackStackChangedListener() {
        public void onBackStackChanged() {
            // Update your UI here.
        }
    });
1
répondu Lalit Sharma 2014-01-28 09:12:45

si vous utilisez FragmentActivity. alors faites comme ceci

appelez d'abord ceci à l'intérieur de votre Fragment.

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

et ensuite appeler onBackPressed méthode à côté de votre parent FragmentActivity classe.

@Override
public void onBackPressed() {
  //super.onBackPressed();
  //create a dialog to ask yes no question whether or not the user wants to exit
  ...
}
1
répondu hash 2014-12-16 06:46:42

ajoutez ce code dans votre activité

@Override

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

et ajouter cette ligne dans votre Fragment avant commit ()

ft.addToBackStack("Un nom");

1
répondu Ravi 2015-03-20 09:37:37

Pour Ceux Qui Utilisent Un Fragment Statique

dans un cas si vous avez un fragment statique alors il serait préférable. Créer un objet instance de votre fragment

private static MyFragment instance=null;

dans onCreate() de MyFragment initialiser une instance de la

  instance=this;

aussi faire une fonction pour obtenir L'Instance

 public static MyFragment getInstance(){
   return instance;
}

aussi faire des fonctions

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
}

dans votre activité vous pouvez faire

@Override
public void onBackPressed() {

    if (MyFragment.getInstance().allowBackPressed()) { 
        MyFragment.getInstance().performSomeAction();
    }
    else{
        super.onBackPressed();
    }
}
1
répondu Muhammad Adil 2015-05-08 06:41:35

dans la classe de fragment mettez ce code pour l'événement de retour:

 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;
            }
        } );
1
répondu tej shah 2015-07-23 17:41:06

contrôle de la backstack fonctionne parfaitement


@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);
}
0
répondu Devrath 2014-11-19 09:30:41

dans votre méthode oncreateView() vous devez écrire ce code et dans la condition KEYCODE_BACk vous pouvez écrire quelle que soit la fonctionnalité que vous voulez

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; 
    } 
}); 
-2
répondu Raj Kumar 2016-03-21 10:36:06