Fragmentlebenszyklus - Welche Methode wird beim Ein- / Ausblenden aufgerufen?


99

Ich verwende die folgende Methode, um zwischen Fragmenten (in meinem NavigationDrawer) zu wechseln, indem ich sie ein- / ausblende.

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

Was mir unklar ist, ist, welche Methode des Fragment-Lebenszyklus aufgerufen wird, wenn ich sie ein- oder ausblende? (Da es keine Methode wie onShow () oder onHide () gibt, bin ich mir nicht ganz sicher, was ich verwenden soll). Ich möchte bestimmte Aktionen ausführen, wenn ein bestimmtes Fragment ein- und ausgeblendet wird.


wenn Sie anrufen Fragment.show () dann später an einem gewissen Punkt, die Fragment Auslöser onCreate(), gefolgt von onCreateDialog(), gefolgt vononCreateView()
Jemand Irgendwo

Antworten:


122

Ähnlich wie im Aktivitätslebenszyklus ruft Android onStart () auf, wenn das Fragment sichtbar wird. onStop()wird normalerweise aufgerufen, wenn das Fragment unsichtbar wird, kann aber auch später aufgerufen werden.

Abhängig von Ihrem Layout kann Android onStart()sogar aufrufen , wenn Ihr Fragment noch nicht sichtbar ist, aber zu einem sichtbaren übergeordneten Container gehört. Dies ist beispielsweise gültig, für android.support.v4.view.ViewPagerdie Sie die Fragment.setUserVisibleHint()Methode überschreiben müssen . Auf jeden Fall, wenn Sie austragen BroadcastReceivers oder andere Zuhörer registrieren / müssen, können Sie sicher nutzen onStart()und onStop()Methoden , weil diese immer aufgerufen werden.

Hinweis: Einige Fragmentcontainer können unsichtbare Fragmente starten. Um mit dieser Situation umzugehen, können Sie überschreiben Fragment.onHiddenChanged(boolean hidden). Gemäß der Dokumentation muss ein Fragment sowohl gestartet als auch sichtbar (nicht ausgeblendet) sein , um für den Benutzer sichtbar zu sein.

Update: Wenn Sie verwenden, android.support.v4.widget.DrawerLayoutbleibt ein Fragment unter der Schublade gestartet und sichtbar, auch wenn die Schublade geöffnet ist. In diesem Fall müssen Sie den Einsatz DrawerLayout.setDrawerListener()und hören onDrawerClosed()und onDrawerOpened()Rückrufe.


14
onStopund onPausewerden nicht aufgerufen, wenn ein Fragment mithilfe einer Transaktion unsichtbar wird. Trotzdem onHiddenChangedheißt es wie vorgeschlagen s1rius Antwort
Yoann Hercouet

Dies funktioniert in NavigationDrawer nicht. onHiddenChanged wird in der v4 / v11-Unterstützungsbibliothek nicht aufgerufen. onStart und onResume werden auch nicht jedes Mal aufgerufen, wenn das Schubladenlayout geöffnet wird.
Drdrej

@drdrej Das Problem ist, dass die Schublade das Fragment darunter nicht vollständig versteckt. Wenn Sie DrawerLayout aus der Support-Bibliothek verwenden, müssen Sie DrawerListener verwenden.
Sergej Shafarenka

69

Ich überschreibe diese Methode und löse mein Problem:

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

1
Versucht, keine Lösung zu finden, aber setUserVisibleHintwie in stackoverflow.com/a/18375436/1815624 gezeigt funktioniert
CrandellWS

36

Natürlich können Sie die folgende Methode verwenden, um dies zu tun:

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

Und man kann leicht erkennen, ob das Fragment für den Benutzer sichtbar ist oder nicht, indem mangetUserVisibleHint()
ARiF

2
setUserVisibleHint funktioniert mit View Pager, jedoch nicht mit regulären Fragmentcontainern.
MikeL

Danke das löst mein Problem :)
RAJESH KUMAR ARUMUGAM

Dies hat bei ViewPager bei mir funktioniert. onHiddenChanged hat nicht funktioniert.
Live-Love

Mein Problem gelöst!
Jad Chahine

3

Das Verhalten des Fragment-in-View-Pagers unterscheidet sich beim regulären Fragment-Container.

Versuchen Sie diesen 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;
    }

2

Versuchen Sie diesen 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

Sie können 'onCreateView' (oder 'onActivityCreated') und 'onHiddenChanged' verwenden. Verwenden Sie 'onCreateView' für die erste Show und 'onHiddenChanged' für die spätere. 'setMenuVisibility' wird bei der Transaktionssteuerung nicht aufgerufen.

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

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

onHiddenChanged () wird nicht mit meinem Fragment
aufgerufen

1

Versuchen Sie dies einfach in Ihrem 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;
    }
}

Und erstellen Sie diesen Code in onCreateView () :

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

isVisibleToUser && getView() != nullhat perfekt für mich funktioniert!
Bobby

1

Eine andere Möglichkeit, die Fragmentmethode aufzurufen, wenn das Fragment sichtbar ist und Sie Viewpager in Aktivitäten verwenden.

// Zunächst erstellen Sie eine Schnittstelle

public interface ShowFragmentVisible{
      public void showFragment();}

// Danach wird diese Schnittstelle so in Fragment implementiert

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

// Jetzt geht deine Aktivität, dann erstelle ich ein Objekt der Schnittstelle und rufe es beim addOnViewpagerListener auf

   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

0

setUserVisibleHintvorher anrufen onCreateView. und Sie können keine Ansicht in setUserVisibleHint aktualisieren, die ich verwende

public void setMenuVisibility(final boolean visible)

für Sichtbarkeit und onHiddenChanged () hat nicht zum ersten Mal aufgerufen . Es wird aufgerufen, wenn sich der verborgene Zustand ändert. weil a fragment is visible by default. Um diese Methode zum ersten Mal zu erreichen, müssen Sie sie aufrufen, mFragmentTransaction.hide(oldFragment)dann funktioniert sie

Hinweis

Wenn Sie den setUserVisible-Hinweis verwenden und die Ansicht aktualisieren möchten, verwenden Sie diese Methode


0

Natürlich könnten Sie überschreiben setUserVisibleHintoder setMenuVisibilityaber wenn Sie auf Contextoder zugreifen müssen Activity, werden sie dort null sein! Es gibt eine andere Methode, bei onStartder der Kontext immer verfügbar ist. Sie wird jedoch beim Erstellen eines Fragments nur einmal aufgerufen. Wenn Sie in einem Pager zwischen Ihren Fragmenten wechseln, werden Sie feststellen, dass sie in der zweiten Ansicht und danach nicht aufgerufen wird .

Also ... was soll ich jetzt tun?

Die Problemumgehung ist recht einfach und kann sowohl onStartfür den ersten als auch setMenuVisibilityfür den späteren Besuch verwendet werden. Ihr Code wird wahrscheinlich wie folgt aussehen:

Fragmentklasse:

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

Dieser Weg Contextsteht der doSth()Methode immer zur Verfügung .


0

Nur das hat bei mir funktioniert !! und setUserVisibleHint(...)ist jetzt veraltet (ich habe am Ende Dokumente angehängt), was bedeutet, dass einige andere Antworten veraltet sind ;-)

public class FragmentFirewall extends Fragment {
    /**
     * Required cause "setMenuVisibility(...)" is not guaranteed to be
     * called after "onResume()" and/or "onCreateView(...)" method.
     */
    protected void didVisibilityChange() {
        Activity activity = getActivity();
        if (isResumed() && isMenuVisible()) {
            // Once resumed and menu is visible, at last
            // our Fragment is really visible to user.
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        didVisibilityChange();
    }

    @Override
    public void setMenuVisibility(boolean visible) {
        super.setMenuVisibility(visible);
        didVisibilityChange();
    }
}

Getestet und funktioniert NaviagationDrawerauch, isMenuVisible()wird es immer wieder geben true(und onResume()scheint genug, aber wir wollen auch unterstützen ViewPager).

setUserVisibleHintist veraltet. Wenn Überschreiben dieser Methode implementiert Verhalten , wenn nebenbei truesollte bewegt werden Fragment.onResume(), und Verhalten implementiert , wenn nebenbei falsesollte bewegt werden Fragment.onPause().

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.