Fragment lifecycle - metode mana yang dipanggil saat show / hide?

99

Saya menggunakan metode berikut untuk beralih di antara Fragmen (di NavigationDrawer saya) dengan menampilkan / menyembunyikannya.

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

Yang tidak saya jelaskan adalah metode siklus hidup Fragmen mana yang dipanggil saat saya menampilkan atau menyembunyikannya? (karena tidak ada metode seperti onShow () atau onHide () saya tidak yakin apa yang harus digunakan). Saya ingin melakukan tindakan tertentu setelah menampilkan dan menyembunyikan Fragmen tertentu.

Philipp Jahoda
sumber
ketika Anda memanggil Fragment.show () maka di beberapa titik kemudian, fragmen terpicu onCreate(), diikuti oleh onCreateDialog(), diikuti olehonCreateView()
Someone Somewhere

Jawaban:

122

Mirip dengan daur hidup aktivitas, Android memanggil onStart () ketika fragmen menjadi terlihat. onStop()biasanya dipanggil saat fragmen tidak terlihat, tetapi bisa juga dipanggil nanti.

Bergantung pada tata letak Anda, Android bisa memanggil onStart()meskipun Fragmen Anda belum terlihat, tetapi itu milik penampung induk yang terlihat. Misalnya, ini berlaku android.support.v4.view.ViewPageryang mengharuskan Anda untuk mengganti Fragment.setUserVisibleHint()metode. Bagaimanapun, jika Anda perlu mendaftarkan / membatalkan pendaftaran BroadcastReceivers atau pendengar lainnya, Anda dapat menggunakan onStart()dan onStop()metode dengan aman karena metode tersebut akan dipanggil selalu.

Catatan: Beberapa wadah fragmen dapat membuat fragmen tak terlihat dimulai. Untuk menangani situasi ini, Anda dapat mengganti Fragment.onHiddenChanged(boolean hidden). Menurut dokumentasi , fragmen harus dimulai dan terlihat (tidak disembunyikan) , agar dapat dilihat oleh pengguna.

Pembaruan: Jika Anda menggunakan, android.support.v4.widget.DrawerLayoutmaka fragmen di bawah laci tetap dimulai dan terlihat bahkan saat laci terbuka. Dalam hal ini Anda perlu menggunakan DrawerLayout.setDrawerListener()dan mendengarkan onDrawerClosed()serta onDrawerOpened()callback.

sergej shafarenka
sumber
14
onStopdan onPausetidak dipanggil saat fragmen tidak terlihat menggunakan transaksi. Namun demikian onHiddenChangeddisebut sebagai jawaban s1rius
Yoann Hercouet
Ini tidak berfungsi di NavigationDrawer. onHiddenChanged tidak dipanggil di dukungan v4 / v11 lib. onStart dan onResume juga tidak akan dipanggil setiap saat, saat layout drawer terbuka.
drdrej
@drdrej Masalahnya adalah bahwa laci tidak menyembunyikan fragmen di bawah sepenuhnya. Jika Anda menggunakan DrawerLayout dari pustaka dukungan, Anda perlu menggunakan DrawerListener.
sergej shafarenka
69

Saya @Override metode ini dan menyelesaikan masalah saya:

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) {
        //do when hidden
    } else {
       //do when show
    }
}
s1rius
sumber
1
Mencoba untuk tidak menyelesaikan tetapi menggunakan setUserVisibleHintseperti yang ditunjukkan dalam stackoverflow.com/a/18375436/1815624 bekerja
CrandellWS
36

tentu saja Anda dapat @Override metode berikut untuk melakukannya:

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            // Do your Work
        } else {
            // Do your Work
        }
    }
Biraj Zalavadia
sumber
Dan orang dapat dengan mudah mengetahui apakah fragmen dapat dilihat oleh pengguna atau tidak dengan menelepongetUserVisibleHint()
ARiF
2
setUserVisibleHint berfungsi dengan view pager, tetapi tidak dengan container fragmen biasa.
MikeL
Terima kasih ini Memecahkan Masalah Saya :)
RAJESH KUMAR ARUMUGAM
Ini bekerja untuk saya di ViewPager. onHiddenChanged tidak berfungsi.
cinta hidup
Memecahkan masalah saya!
Jad Chahine
3

Fragmen dalam tampilan pager berbeda dengan wadah fragmen biasa.

Coba kode ini:

    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;
    }
Alan Yuan
sumber
2

Coba kode ini:

@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
}
Ahmad Aghazadeh
sumber
2

Anda bisa menggunakan 'onCreateView' (atau 'onActivityCreated') dan 'onHiddenChanged'. Gunakan 'onCreateView' untuk pertunjukan pertama dan gunakan 'onHiddenChanged' untuk nanti. 'setMenuVisibility' tidak dipanggil di kontrol transaksi.

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

@Override
public void onHiddenChanged(boolean hidden) {
    if (!hidden) {
        // fragment will show 
    }
    else {
        // fragment will hide
    }
}
hoi
sumber
onHiddenChanged () tidak dipanggil dengan fragmen saya
matdev
1

Coba saja ini di setUserVisibleHint () Anda

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

Dan buat kode ini di onCreateView () :

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  if(!isActive){
      init();
  }
}
buluh
sumber
isVisibleToUser && getView() != nullbekerja sempurna untuk saya!
bobby
1

Cara lain untuk memanggil metode fragmen saat fragmen terlihat dan Anda menggunakan viewpager dalam aktivitas.

// pertama-tama Anda membuat antarmuka

public interface ShowFragmentVisible{
      public void showFragment();}

// Setelah itu antarmuka ini diimplementasikan di dalam Fragmen seperti itu

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

// Sekarang masuklah Aktivitas Anda lalu buat objek antarmuka dan panggil di dalamnya saat 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
Jatin Bansal
sumber
0

setUserVisibleHintmenelepon sebelumnya onCreateView. dan Anda tidak dapat memperbarui Tampilan apa pun di dalam setUserVisibleHint yang saya gunakan

public void setMenuVisibility(final boolean visible)

untuk visibilitas dan onHiddenChanged () tidak memanggil untuk pertama kalinya . itu memanggil ketika status tersembunyi berubah. karena a fragment is visible by default. Untuk mencapai metode ini untuk pertama kalinya Anda harus memanggil mFragmentTransaction.hide(oldFragment)maka itu akan berhasil

Catatan

jika Anda ingin menggunakan petunjuk setUserVisible dan memperbarui Tampilan Gunakan metode ini

AndroidGeek
sumber
0

Tentu saja Anda bisa menimpanya setUserVisibleHint atau setMenuVisibilitytetapi jika Anda perlu mengakses Contextatau Activity, mereka akan menjadi nol di sana! Ada metode lain onStartyang selalu memiliki konteks yang tersedia, tetapi itu hanya akan dipanggil satu kali setelah pembuatan fragmen dan jika Anda mulai berpindah antar fragmen dalam pager, Anda akan melihat bahwa itu tidak akan dipanggil dalam tampilan kedua dan setelahnya .

Jadi ... apa yang harus dilakukan sekarang?

Solusinya cukup mudah, gunakan onStartuntuk kunjungan pertama dan setMenuVisibilityselanjutnya. Kode Anda mungkin akan terlihat seperti di bawah ini:

Kelas fragmen:

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

Cara ini Contextakan selalu tersedia untuk doSth()metode.

AmiNadimi
sumber
0

Hanya ini yang berhasil untuk saya !! dan setUserVisibleHint(...)sekarang tidak digunakan lagi (saya melampirkan dokumen di bagian akhir), yang berarti beberapa jawaban lain tidak digunakan lagi ;-)

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

Diuji dan bekerja dengan NaviagationDrawerbaik, isMenuVisible()akan selalu ada kembali true(dan onResume()tampaknya cukup, tetapi kami ingin mendukung ViewPagerjuga).

setUserVisibleHintsudah ditinggalkan. Jika menimpa metode ini, perilaku yang diterapkan saat meneruskan trueharus dipindahkan ke Fragment.onResume(), dan perilaku yang diterapkan saat meneruskan falseharus dipindahkan ke Fragment.onPause().

Top-Master
sumber