web-dev-qa-db-fra.com

Cycle de vie des fragments - quelle méthode est utilisée pour afficher / masquer?

J'utilise la méthode suivante pour basculer entre les fragments (dans mon NavigationDrawer) en les affichant/les masquant.

protected void showFragment(int container, Fragment fragment, String tag, String lastTag, boolean addToBackStack ) {

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();

        if ( lastTag != null && !lastTag.equals("")) {
            Fragment lastFragment = fragmentManager.findFragmentByTag( lastTag );
            if ( lastFragment != null ) {
                transaction.hide( lastFragment );
            }
        }

        if ( fragment.isAdded() ) {
            transaction.show( fragment );
        }
        else {
            transaction.add( container, fragment, tag );
        }

        if ( addToBackStack ) {
            transaction.addToBackStack( tag );
        }

        transaction.commit();

        // set the active tag
        activeFragTag = tag;
    }

Ce que je ne sais pas, c'est quelle méthode du cycle de vie de Fragments est appelée quand je le montre ou le cache? (puisqu'il n'y a pas de méthode telle que onShow () ou onHide (), je ne sais pas trop quoi utiliser ). Je veux effectuer des actions spécifiques lors de l'affichage et de la dissimulation d'un certain fragment.

92
Philipp Jahoda

Semblable au cycle de vie d'une activité, Android appelle onStart () lorsque le fragment devient visible. onStop() est normalement appelé lorsque le fragment devient invisible, mais il peut également être appelé plus tard.

Selon votre mise en page Android peut appeler onStart()) même lorsque votre fragment n'est pas encore visible, mais qu'il appartient à un conteneur parent visible. Par exemple, ceci est valable pour Android.support.v4.view.ViewPager Qui vous oblige à remplacer Fragment.setUserVisibleHint() méthode. Dans tous les cas, si vous devez enregistrer/désenregistrer BroadcastReceivers ou d’autres écouteurs, vous pouvez utiliser en toute sécurité onStart() et onStop() méthodes car elles seront appelées toujours.

Remarque: Certains conteneurs de fragments peuvent conserver les fragments invisibles démarrés. Pour gérer cette situation, vous pouvez remplacer Fragment.onHiddenChanged(boolean hidden) . Selon la documentation , un fragment doit être à la fois démarré et visible (non caché), pour être visible à l'utilisateur.

Mise à jour: Si vous utilisez Android.support.v4.widget.DrawerLayout, Un fragment situé sous le tiroir reste démarré et visible même lorsque le tiroir est ouvert. Dans ce cas, vous devez utiliser DrawerLayout.setDrawerListener() et écouter les rappels onDrawerClosed() et onDrawerOpened().

109
sergej shafarenka

Je @ Override cette méthode et résoudre mon problème:

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) {
        //do when hidden
    } else {
       //do when show
    }
}
53
s1rius

bien sûr, vous pouvez @Overriede suivre la méthode pour le faire:

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            // Do your Work
        } else {
            // Do your Work
        }
    }
34
Biraj Zalavadia

Le comportement de pagineur en vue de vue est différent avec le conteneur de fragments régulier.

Essayez ce code:

    boolean mIsVisibleToUser;

    /**
     * is visible to user
     */
    public void show() {
        //do when show
    }

    /**
     * is invisible to user
     */
    public void hide() {
        //do when gone
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!mIsVisibleToUser && getUserVisibleHint()) {
            mIsVisibleToUser = true;
            show();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mIsVisibleToUser && getUserVisibleHint()) {
            mIsVisibleToUser = false;
            hide();
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isResumed()) {
            if (mIsVisibleToUser != isVisibleToUser) {
                mIsVisibleToUser = isVisibleToUser;
                if (isVisibleToUser) show();
                else hide();
            }
        }
    }

    public boolean isVisibleToUser() {
        return mIsVisibleToUser;
    }
3
Alan Yuan

Essayez ce code:

@Override
public void setUserVisibleHint(boolean visible)
{
    super.setUserVisibleHint(visible);
    if (visible && isResumed())
    {
         onResume();
    }
}

@Override
public void onResume()
{
    super.onResume();
    if (!getUserVisibleHint())
    {
        return;
    }

    //Add your code this section
}
2
Ahmad Aghazadeh

Essayez ceci dans votre setUserVisibleHint ()

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if(isVisibleToUser && getView() != null){
        isActive = true;
        init();
    }else if(isVisibleToUser && getView() == null){
        isActive = false;
    }else{
        isActive = true;
    }
}

Et créez ce code dans onCreateView ():

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  if(!isActive){
      init();
  }
}
1
reed

Vous pouvez utiliser 'onCreateView' (ou 'onActivityCreated') et 'onHiddenChanged'. Utilisez 'onCreateView' pour la première émission et utilisez 'onHiddenChanged' pour plus tard. 'setMenuVisibility' n'est pas appelé lors du contrôle de transaction.

@Override
public View OnCreateView() {
   // fragment will show first
}

@Override
public void onHiddenChanged(boolean hidden) {
    if (!hidden) {
        // fragment will show 
    }
    else {
        // fragment will hide
    }
}
1
hoi

Une autre façon d'appeler la méthode fragment lorsque fragment est visible et que vous utilisez viewpager en activité.

// tout d'abord vous créez une interface

public interface ShowFragmentVisible{
      public void showFragment();}

// Ensuite, cette interface est implémentée dans Fragment comme ça

      public class MyFragment extends Fragment implements 
         ShowFragmentVisible {
            @Override
public void showFragment() {
}

// va maintenant votre activité puis crée un objet d'interface et appelle à l'intérieur quand addOnViewpagerListener

   ShowFragmentVisible showFragmentVisible;

@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);

    if (fragment instanceof ShowFragmentVisible) {
        showFragmentVisible = (ShowFragmentVisible) fragment;
    }

}
     //your viewpager method
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            if (position==0){
                showFragmentVisible.showFragment();

           }

        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });


this is another alternative,but its work for me successfully
1
Jatin Bansal

setUserVisibleHint appel avant onCreateView. et vous ne pouvez mettre à jour aucune vue à l'intérieur de setUserVisibleHint que j'utilise

public void setMenuVisibility(final boolean visible)

pour visibilité et onHiddenChanged () n'a pas appelé pour la première fois . il appelle quand l'état caché change. parce qu'un fragment is visible by default. Afin de réaliser cette méthode pour la première fois, vous devez appeler mFragmentTransaction.hide(oldFragment) puis cela fonctionnera

Remarque

si vous voulez utiliser la directive setUserVisible et mettre à jour la vue Utilisez cette méthode

0
Xar E Ahmer

Bien sûr, vous pouvez remplacer setUserVisibleHint ou setMenuVisibility, mais si vous devez accéder à Context ou Activity, ils seront nuls! Il y a une autre méthode onStart qui a toujours le contexte disponible, mais elle ne sera appelée qu'une fois lors de la création d'un fragment et si vous commencez à vous déplacer entre vos fragments dans un pager, vous verrez qu'il ne sera pas obtenu. appelé en deuxième vue et après.

Alors ... que faire maintenant?

La solution de contournement est assez simple, utilisez onStart pour la première visite et setMenuVisibility pour les visites suivantes. Votre code ressemblera probablement à celui ci-dessous:

Classe de fragment:

public class MyFragmentClass{
    private boolean isCurrentVisible = false;
...

@Override
public void onStart() {
    super.onStart();
    if (isCurrentVisible)
        doSth();
}

@Override
public void setMenuVisibility(boolean menuVisible){
    super.setMenuVisibility(menuVisible);
    this.isCurrentVisible = menuVisible;
    if(menuVisible && getContext() != null)
        doSth();
}

De cette façon, Context sera toujours disponible pour la méthode doSth().

0
AmiNadimi