Cykl życia fragmentu - która metoda jest wywoływana po wyświetleniu / ukryciu?


99

Używam następującej metody, aby przełączać się między fragmentami (w moim NavigationDrawer), pokazując / ukrywając je.

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

Nie mam pewności, która metoda cyklu życia fragmentów jest wywoływana, gdy ją pokazuję lub ukrywam? (ponieważ nie ma metody takiej jak onShow () lub onHide (), nie jestem do końca pewien, której użyć). Chcę wykonać określone czynności po wyświetleniu i ukryciu określonego Fragmentu.


kiedy wywołujesz Fragment.show (), to w pewnym momencie później następuje wyzwolenie fragmentu onCreate(), po którym onCreateDialog()następuje, a następnieonCreateView()
Someone Somewhere

Odpowiedzi:


122

Podobnie jak w przypadku cyklu życia działania, Android wywołuje metodę onStart (), gdy fragment staje się widoczny. onStop()jest zwykle wywoływana, gdy fragment staje się niewidoczny, ale można ją również wywołać później.

W zależności od układu Android może wywoływać onStart()nawet wtedy, gdy Twój fragment nie jest jeszcze widoczny, ale należy do widocznego kontenera nadrzędnego. Na przykład jest to ważne, w przypadku android.support.v4.view.ViewPagerktórego wymaga się zastąpienia Fragment.setUserVisibleHint()metody. W każdym razie, jeśli chcesz zarejestrować / wyrejestrować BroadcastReceivers lub innych słuchaczy, możesz bezpiecznie używać metod onStart()i onStop(), ponieważ będą one wywoływane zawsze.

Uwaga: Niektóre pojemniki na fragmenty mogą uruchamiać niewidoczne fragmenty. Aby poradzić sobie z tą sytuacją, możesz zmienić Fragment.onHiddenChanged(boolean hidden). Zgodnie z dokumentacją fragment musi być zarówno uruchomiony, jak i widoczny (nie ukryty) , aby był widoczny dla użytkownika.

Aktualizacja: Jeśli używasz, android.support.v4.widget.DrawerLayoutfragment poniżej szuflady pozostaje uruchomiony i widoczny, nawet gdy szuflada jest otwarta. W takim przypadku musisz używać DrawerLayout.setDrawerListener()i nasłuchiwać onDrawerClosed()oraz onDrawerOpened()wywołań zwrotnych.


14
onStopi onPausenie są wywoływane, gdy fragment staje się niewidoczny przy użyciu transakcji. Niemniej jednak onHiddenChangedjest nazywany, jak sugeruje odpowiedź s1rius
Yoann Hercouet

To nie działa w NavigationDrawer. onHiddenChanged nie jest wywoływany w przypadku obsługi lib v4 / v11. onStart i onResume będą również wywoływane nie za każdym razem, gdy otworzy się układ szuflady.
drdrej

@drdrej Problem w tym, że szuflada nie ukrywa w całości fragmentu poniżej. Jeśli używasz DrawerLayout z biblioteki wsparcia, musisz użyć DrawerListener.
sergej shafarenka

69

Nadpisuję tę metodę i rozwiązuję problem:

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

1
Nie udało się rozwiązać problemu, ale działa setUserVisibleHinttak, jak pokazano na stackoverflow.com/a/18375436/1815624
CrandellWS

36

oczywiście możesz @Override następującą metodę, aby to zrobić:

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

I można łatwo getUserVisibleHint()
sprawdzić

2
setUserVisibleHint działa z przeglądarką stron, ale nie ze zwykłym kontenerem fragmentów.
MikeL

Dzięki, to rozwiązuje mój problem :)
RAJESH KUMAR ARUMUGAM

To zadziałało dla mnie na ViewPager. onHiddenChanged nie działa.
miłość na żywo

Rozwiązał mój problem!
Jad Chahine,

3

Fragment w widoku Zachowanie pagera jest inne w przypadku zwykłego kontenera fragmentów.

Wypróbuj ten kod:

    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

Wypróbuj ten kod:

@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

Możesz użyć „onCreateView” (lub „onActivityCreated”) i „onHiddenChanged”. Użyj „onCreateView” do pierwszego pokazu, a „onHiddenChanged” na później. „setMenuVisibility” nie jest wywoływana podczas kontroli transakcji.

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

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

onHiddenChanged () nie jest wywoływany z moim fragmentem
matdev

1

Po prostu spróbuj tego w swoim 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;
    }
}

I utwórz ten kod w onCreateView () :

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

isVisibleToUser && getView() != nulldziałało idealnie dla mnie!
bobby

1

Innym sposobem na wywołanie metody fragment, gdy fragment jest widoczny i używasz viewpagera w działaniu.

// przede wszystkim tworzysz interfejs

public interface ShowFragmentVisible{
      public void showFragment();}

// Następnie ten interfejs implementuje wewnątrz Fragment w ten sposób

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

// Teraz idzie Twoja aktywność, a następnie utwórz obiekt interfejsu i wywołaj wewnątrz, gdy 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

0

setUserVisibleHintzadzwoń wcześniej onCreateView. i nie możesz zaktualizować żadnego widoku wewnątrz setUserVisibleHint, którego używam

public void setMenuVisibility(final boolean visible)

for visibility, a onHiddenChanged () nie wywołał po raz pierwszy . wywołuje, gdy zmienia się stan ukryty. ponieważ fragment is visible by default. Aby uzyskać tę metodę po raz pierwszy, musisz zadzwonić, mFragmentTransaction.hide(oldFragment)wtedy zadziała

Uwaga

jeśli chcesz użyć wskazówki setUserVisible i zaktualizować Widok Użyj tej metody


0

Oczywiście można zastąpić setUserVisibleHintalbo setMenuVisibilityale jeśli trzeba dostęp Contextlub Activity, będą tam zerowa! Jest inna metodaonStart która zawsze ma pod ręką kontekst, ale zostanie wywołana tylko raz po utworzeniu fragmentu i jeśli zaczniesz poruszać się między swoimi fragmentami na pagerze, zobaczysz, że nie zostanie wywołana w drugim widoku i później .

Więc ... co teraz zrobić?

Obejście jest dość łatwe, użyj onStartprzy pierwszej wizycie i setMenuVisibilityprzy późniejszych. Twój kod prawdopodobnie będzie wyglądał jak poniżej:

Klasa fragmentu:

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

W ten sposób Contextzawsze będzie dostępna doSth()metoda.


0

Tylko to zadziałało dla mnie !! i setUserVisibleHint(...)jest teraz przestarzały (na końcu dołączyłem dokumenty), co oznacza, że ​​niektóre inne odpowiedzi są przestarzałe ;-)

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

Przetestowany i działa NaviagationDrawerrównież z, isMenuVisible()zawsze wróci true(i onResume()wydaje się wystarczający, ale chcemy ViewPagerteż wspierać ).

setUserVisibleHintjest przestarzałe. W przypadku zastępowania tej metody zachowanie zaimplementowane podczas przekazywania truepowinno zostać przeniesione do Fragment.onResume(), a zachowanie zaimplementowane podczas przekazywania falsepowinno zostać przeniesione doFragment.onPause() .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.