Parça yaşam döngüsü - gösterme / gizleme sırasında hangi yöntem çağrılır?


99

Parçalar arasında (NavigationDrawer'ımda) göstererek / gizleyerek geçiş yapmak için aşağıdaki yöntemi kullanıyorum.

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

Net olmadığım şey, onu gösterirken veya gizlediğimde Fragments yaşam döngüsünün hangi yönteminin çağrıldığı? (onShow () veya onHide () gibi bir yöntem olmadığından, ne kullanacağımı tam olarak bilmiyorum). Belirli bir Parçayı gösterme ve gizleme üzerine belirli eylemler gerçekleştirmek istiyorum.


Aradığınızda ) Fragment.show ( sonradan bir noktada, daha sonra parça tetikleyiciler onCreate()ardından onCreateDialog(), ardındanonCreateView()
Birisi bir yerde

Yanıtlar:


122

Etkinlik yaşam döngüsüne benzer şekilde Android , parça görünür hale geldiğinde onStart () öğesini çağırır . onStop()normalde parça görünmez hale geldiğinde denir, ancak daha sonra da çağrılabilir.

Düzeninize bağlı olarak Android, onStart()Fragmentiniz henüz görünür olmadığında, ancak görünür bir ana kapsayıcıya ait olduğunda bile arayabilir . Örneğin, bu, yöntemi android.support.v4.view.ViewPagergeçersiz kılmanızı gerektiren için geçerlidir Fragment.setUserVisibleHint(). Her durumda, BroadcastReceiver'ları veya diğer dinleyicileri kaydettirmeniz / kaydını silmeniz gerekirse, güvenle onStart()ve onStop()yöntemleri kullanabilirsiniz çünkü bunlar her zaman çağrılacaktır.

Not: Bazı parça kapları görünmez parçaların başlamasını sağlayabilir. Bu durumu ele almak için geçersiz kılabilirsiniz Fragment.onHiddenChanged(boolean hidden). Belgelere göre, kullanıcının görebilmesi için bir parçanın hem başlatılması hem de görünür olması (gizli olmaması) gerekir.

Güncelleme: Eğer kullanırsanız android.support.v4.widget.DrawerLayout, çekmecenin altındaki bir parça başlatılmış ve çekmece açıkken bile görünür durumda kalır. Bu durumda , geri aramaları kullanmanız DrawerLayout.setDrawerListener()ve dinlemeniz gerekir .onDrawerClosed()onDrawerOpened()


14
onStopve onPausebir işlem kullanılarak bir parça görünmez hale geldiğinde çağrılmaz. Yine onHiddenChangeds1rius cevabı da anlaşılacağı gibi denir
Yoann Hercouet

Bu, NavigationDrawer'da çalışmaz. onHiddenChanged v4 / v11 destek kitaplığında çağrılmaz. onStart ve onResume, çekmece düzeni açıldığında her seferinde çağrılmaz.
drdrej

@drdrej Sorun şu ki, çekmecenin altındaki parçayı tamamen gizlemiyor. Destek kitaplığından DrawerLayout kullanıyorsanız, DrawerListener kullanmanız gerekir.
sergej shafarenka

70

Ben @ Bu yöntemi geçersiz kılıyorum ve sorunumu çözüyorum:

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

1
Hiçbir kararlılığının çalıştı ancak kullanarak setUserVisibleHintgösterildiği gibi stackoverflow.com/a/18375436/1815624 eserleri
CrandellWS

36

Elbette bunu yapmak için aşağıdaki yöntemi @Override edebilirsiniz:

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

Ve arayarak getUserVisibleHint()
parçanın

2
setUserVisibleHint, görünüm sayfalayıcıyla çalışır ancak normal parça kapsayıcıyla çalışmaz.
MikeL

Teşekkürler Bu
Sorunumu Çözüyor

Bu benim için ViewPager'da çalıştı. onHiddenChanged çalışmadı.
live-love

Sorunumu çözdüm!
Jad Chahine

3

Görünüm sayfalayıcı davranışındaki parça, normal parça kapsayıcısıyla farklıdır.

Bu kodu deneyin:

    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

Bu kodu deneyin:

@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

'OnCreateView' (veya 'onActivityCreated') ve 'onHiddenChanged' kullanabilirsiniz. İlk gösteri için 'onCreateView' kullanın ve daha sonra 'onHiddenChanged' kullanın. 'setMenuVisibility' işlem kontrolünde çağrılmaz.

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

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

onHiddenChanged () parçamla çağrılmıyor
matdev

1

Bunu setUserVisibleHint () içinde deneyin

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

Ve bu kodu onCreateView () 'da oluşturun :

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

isVisibleToUser && getView() != nullbenim için mükemmel çalıştı!
bobby

1

Parça görünür olduğunda parça yöntemini çağırmanın başka bir yolu da etkinlik içinde görüntüleyiciyi kullanır.

// her şeyden önce bir arayüz oluşturursunuz

public interface ShowFragmentVisible{
      public void showFragment();}

// Bundan sonra bu arayüz Fragment'in içine böyle uygular

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

// Şimdi Etkinliğinize gider, ardından arabirim nesnesini oluşturur ve addOnViewpagerListener olduğunda içeriyi çağırır

   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

setUserVisibleHintönce ara onCreateView. ve kullandığım setUserVisibleHint içinde hiçbir Görünümü güncelleyemezsiniz

public void setMenuVisibility(final boolean visible)

için görünürlük ve onHiddenChanged () ilk kez aramadın . gizli durum değiştiğinde çağırır. çünkü a fragment is visible by default. Bu yöntemi ilk kez elde etmek için aramanız gerekir.mFragmentTransaction.hide(oldFragment) gerekiyor, o zaman işe yarayacak

Not

setUserVisible ipucu kullanmak ve Görünüm'ü güncellemek istiyorsanız Bu yöntemi kullanın


0

Elbette geçersiz kılabilirsiniz setUserVisibleHintveya setMenuVisibilityancak erişmeniz gerekiyorsa Contextveya Activity, orada boş olacaklar! Başka bir yöntem varonStartBağlamı her zaman elinizin altında tutan daha vardır, ancak yalnızca bir parça oluşturulduktan sonra çağrılır ve bir çağrı cihazında parçalarınız arasında hareket etmeye başlarsanız, ikinci görünümde ve daha sonra çağrılmayacağını göreceksiniz. .

Peki şimdi ne yapmalı?

Çözüm oldukça kolaydır, onStartilk ziyaret için ve setMenuVisibilitysonraki ziyaretler için kullanın . Kodunuz muhtemelen aşağıdaki gibi görünecektir:

Parça sınıfı:

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

Bu yol Contexther zaman doSth()yöntem için mevcut olacaktır .


0

Sadece bu benim için çalıştı! ve setUserVisibleHint(...)artık kullanımdan kaldırıldı (sonuna dokümanları ekledim), bu da diğer bazı yanıtların kullanımdan kaldırıldığı anlamına gelir ;-)

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

Test edilmiş ve ile eserler NaviagationDrawerde, orada olduğu gibi isMenuVisible()her zaman dönecektir true(ve onResume()yeterli görünüyor, ama biz desteklemek istiyoruz ViewPagerçok).

setUserVisibleHintkullanımdan kaldırıldı. Bu yöntem geçersiz kılınırsa, trueiçeri Fragment.onResume()aktarılırken uygulanan davranışa taşınmalı ve içeri aktarılırken uygulanan davranış konumuna falsetaşınmalıdır Fragment.onPause().

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.