Bagaimana cara saya mendapatkan fragmen yang sedang ditampilkan?

444

Saya bermain dengan fragmen di Android.

Saya tahu saya dapat mengubah sebuah fragmen dengan menggunakan kode berikut:

FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMgr.beginTransaction();

MyFragment myFragment = new MyFragment(); //my custom fragment

fragTrans.replace(android.R.id.content, myFragment);
fragTrans.addToBackStack(null);
fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragTrans.commit();

Pertanyaan saya adalah, dalam file Java, bagaimana saya bisa mendapatkan instance Fragment yang sedang ditampilkan?

Leem.fin
sumber
1
Kemungkinan rangkap dari Dapatkan objek fragmen saat ini
Sruit A.Suk

Jawaban:

453

Ketika Anda menambahkan fragmen dalam transaksi Anda, Anda harus menggunakan tag.

fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT");

... dan nanti jika Anda ingin memeriksa apakah fragmennya terlihat:

MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
   // add your code here
}

Lihat juga http://developer.android.com/reference/android/app/Fragment.html

ramdroid
sumber
74
Ok, tapi saya perlu cara untuk segera mendapatkan contoh Fragmen yang sedang ditampilkan, tidak secara iteratif memeriksa semua fragmen dan kemudian memutuskan fragmen mana yang sekarang ditampilkan di layar. Saya pikir jawaban Anda memerlukan kode saya untuk memeriksa setiap fragmen saya secara berulang, dan mencari tahu yang terlihat ...
Leem.fin
33
Ya, tetapi mungkin ada lebih dari satu fragmen yang terlihat pada satu waktu. Jadi tidak ada yang seperti "satu-satunya fragmen aktif" ....
ramdroid
6
Ok, walaupun ada beberapa fragmen yang ditampilkan, saya masih membutuhkan cara untuk mendapatkannya ... dan cara yang lebih baik daripada memeriksa setiap fragmen saya secara iteratif. Saya khawatir tentang "dapatkan mereka" metode seperti getDisplayedFragment (), tetapi tidak yakin apakah ada metode seperti itu di Android
Leem.fin
2
Saya tidak tahu mengapa ini menjadi masalah bagi Anda ... Anda biasanya hanya memiliki beberapa fragmen dalam suatu kegiatan dan seharusnya tidak menjadi masalah untuk memeriksa mereka apakah mereka terlihat atau tidak.
ramdroid
12
Mengapa semua orang mengambil jawaban ini? Tentu, ini adalah kode yang bagus tetapi tidak menjawab pertanyaan untuk mendapatkan fragmen tertentu dengan tag .. TAPI Penanya menginginkan fragmen yang saat ini ditampilkan, yang berarti ia tidak tahu fragmen mana yang ditampilkan. Ya, mungkin ada beberapa fragmen, tetapi membaca pertanyaan menyimpulkan hanya 1 fragmen yang ditampilkan di UI .... Maaf harus mengundurkan diri karena tidak menjawab konteks pertanyaan.
angryITguy
410

Saya tahu ini adalah pos lama, tetapi sebelumnya juga mengalami masalah. Menemukan solusi untuk melakukan ini dalam onBackStackChanged()fungsi mendengarkan

  @Override
    public void onBackPressed() {
        super.onBackPressed();

         Fragment f = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
      if(f instanceof CustomFragmentClass) 
        // do something with f
        ((CustomFragmentClass) f).doSomething();

    }

Ini bekerja untuk saya karena saya tidak ingin mengulangi setiap fragmen yang harus saya temukan yang terlihat. Semoga ini bisa membantu orang lain juga.

Sev
sumber
13
Persis apa yang saya cari ketika berhadapan dengan onBackPressed () setelah rotasi layar dengan Drawer Navigasi. Terima kasih telah kembali untuk membagikan ini.
ShortFuse
1
Tidak menemukanFragmentById beralih melalui semua fragmen secara internal? :)
Andrew Senner
46
dalam kasus .getFragmentManagermelaporkan jenis yang tidak kompatibel, seperti yang terjadi dalam kasus saya, itu karena saya menggunakan android.support.app.v4.Fragment, dalam hal ini metode yang tepat untuk digunakan adalahgetSupportFragmentManager
Răzvan Barbu
3
atau Anda dapat menggunakannya findFragmentByTag()sebagai pengganti findFragmentById, jika Anda telah memberikan tag pada fragmen ketika menambahkannya kefragmentManager.beginTransaction() .add(containerID, frag, fragmentTag) .addToBackStack(fragmentTag) .commit();
DeltaCap019
@AndrewSenner, maksudnya dia tidak ingin melakukannya secara eksplisit :)
Farid
161

Berikut adalah solusi saya yang menurut saya berguna untuk skenario fragmen rendah

public Fragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    if(fragments != null){
        for(Fragment fragment : fragments){
            if(fragment != null && fragment.isVisible())
                return fragment;
        }
    }
    return null;
}
Matt Mombrea
sumber
13
fragmentbisa nol dalam skenario tertentu, seperti ketika Anda membuka back stack. Jadi lebih baik digunakan if (fragment != null && fragment.isVisible()).
cprcrack
8
Metode tidak lengkap karena mungkin tidak hanya ada satu fragmen yang terlihat
letroll
Jika tidak ada fragmen yang terlihat, maka fragmentManager.getFragments () akan mengembalikan NULL yang akan mengarah pada NPE yang mengatakan "Mencoba untuk memanggil metode antarmuka 'java.util.Iterator java.util.Iterator java.util.List.iterator ()' pada referensi objek NULL". Oleh karena itu, loop for harus dikelilingi oleh cek sederhana: if (fragments! = Null)
Pranav Mahajan
Bagaimana jika lebih dari satu fragmen terlihat?
Shivaraj Patil
5
Secara teknis ini harus ditandai sebagai jawaban berdasarkan pertanyaan. Penanya ingin fragmen yang ditampilkan saat ini, tidak tahu fragmen mana. Jawaban lain terus mendapatkan fragmen dengan tag
angryITguy
76

Setiap kali Anda menunjukkan fragmen, Anda harus meletakkannya di backstack:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_ENTER_MASK);       
ft.add(R.id.primaryLayout, fragment, tag);
ft.addToBackStack(tag);
ft.commit();        

Dan kemudian ketika Anda perlu mendapatkan fragmen saat ini Anda dapat menggunakan metode ini:

public BaseFragment getActiveFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}
Dmitry_L
sumber
4
Saya cukup yakin teknik ini tidak akan berfungsi untuk Fragmen yang digunakan dengan ViewPager, karena tidak ditambahkan oleh tag. Hanya melempar itu ke sana.
loeschg
3
Tampaknya ini hanya berfungsi saat Anda menelepon addToBackStack(tag), tetapi bagaimana jika Anda tidak ingin menambahkan fragmen ke tumpukan belakang?
cprcrack
1
Ini hanya berfungsi jika tag Anda sama dengan nama tumpukan belakang, yang sepertinya tidak biasa.
Apa yang terjadi jika Anda menambahkan 5 fragmen dalam transaksi yang sama?
Kevin Lam
Mungkin menyenangkan untuk mengatakan bahwa jika Anda memanggil addToBackStack (null) untuk beberapa Fragmen di mana Anda tidak memerlukan nama, metode getName () dapat mengembalikan nol dan Anda mendapatkan NPE. @ dpk, docu mengatakan: Dapatkan nama yang disediakan untuk FragmentTransaction.addToBackStack (String) saat membuat entri ini. Juga, tambahkan cek nol jika EntryCount bernilai 0 dan Anda mencoba menerima entri teratas.
JacksOnF1re
23

Apa yang saya gunakan untuk menemukan fragmen tampilan saat ini adalah dalam kode di bawah ini. Sederhana dan bekerja untuk saya sekarang. Itu berjalan dalam aktivitas yang menyimpan fragmen

    FragmentManager fragManager = this.getSupportFragmentManager();
    int count = this.getSupportFragmentManager().getBackStackEntryCount();
    Fragment frag = fragManager.getFragments().get(count>0?count-1:count);
tainy
sumber
3
Anda harus memeriksa untuk memastikan hitung> 0 sehingga get (hitungan-1) tidak melempar IndexOutofBoundsException
kehers
@ lakukan ini tidak akan memberikan fragmen yang diganti tetapi tidak ditambahkan ke backstack. Benar? Jika ya, bisakah saya mendapatkannya menggunakan argumen tag?
cafebabe1991
Panggilan getFragments tidak akan memberi Anda fragmen urutan yang ditambahkan setelah Anda memanggil popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE) di atasnya, dan menambahkan lebih banyak fragmen.
LEHO
jika aktivitas memiliki lebih dari satu Fragmen yang terlihat, jalan Anda salah. Misalnya: ViewPager dengan Fragmen. seperti yang saya ketahui getBackStackEntryCount () mengembalikan jumlah Transaksi, bukan jumlah fragmen
HungNM2
Anda harus memeriksa fragManager.getFragments().size()bukan getBackStackEntryCount()karena mereka tidak harus sama (yang merupakan kasus saya). Kalau tidak, Anda bisa mendapatkan crash dengan IndexOutOfBoundsException
RustamG
19

Jalan Kotlin;

val currentFragment = supportFragmentManager.fragments.last()
Kafe Mert Ceyhan
sumber
Bekerja pada API 26 dan hanya lebih tinggi
ibit
1
@ibit apa yang Anda maksud dengan hanya bekerja di API 26 dan yang lebih tinggi? Saya mencoba emulator API 19 bekerja dengan baik.
HendraWD
@HendraWD kamu benar! Saya merujuk ke fungsi dalam getFragments()fungsi frameworks , yaitu API 26 dan lebih tinggi.
ibit
2
hati hati. Jika sebelum Anda tidak memiliki tumpukan fragmen, itu dapat menyebabkan pengecualian kosong!
Jetwiz
Ini tidak bekerja? java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment tidak dapat dilemparkan ke Fragment
coolcool1994
13

Itu reaktif :

Observable.from(getSupportFragmentManager().getFragments())
    .filter(fragment -> fragment.isVisible())
    .subscribe(fragment1 -> {
        // Do something with it
    }, throwable1 -> {
        // 
    });
localhost
sumber
7
bagaimana itu reaktif? Anda menggunakan yang bisa diamati tetapi hanya akan memancarkan satu kali
Tim
6
Dan itu hanya kerja keras. Sebuah forloop sederhana yang ditingkatkan akan melakukan hal yang sama, mungkin bahkan lebih cepat.
Peterstev Uremgba
menggunakan aliran reaktif untuk hanya streaming api tidak sepintar itu, pada kenyataannya seperti yang mereka katakan itu adalah berlebihan menggunakan api Java8 uap jika Anda ingin memperlakukan daftar sebagai aliran dan menerapkan api filter
AndroidLover
13

Metode saya didasarkan pada coba / tangkap seperti ini:

MyFragment viewer = null;
    if(getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT) instanceOf MyFragment){
    viewer = (MyFragment) getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT);
}

Tapi mungkin ada cara yang lebih baik ...

Thordax
sumber
1
Pertanyaan saya adalah bagaimana cara mendapatkan fragmen yang ditampilkan saat ini, yang berarti mungkin ada banyak fragmen, saya hanya ingin mendapatkan contoh dari fragmen yang saat ini ditampilkan, mengapa menggunakan (MyFragment) ?? Maksud saya itu bisa berupa tampilan Fragmen di layar ... dan saya ingin mendapatkan yang ditampilkan saat ini.
Leem.fin
MY_TAG_FRAGMENT adalah tag fragmen yang saya buat sebelum menggunakan pengganti, seperti ini: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT);
Thordax
Jika saya memiliki beberapa fragmen, dapatkah saya menggunakan satu tag untuk semua fragmen saat memanggil .replace (...)?
Leem.fin
Ya, tidak masalah, gunakan kode ini: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT); dan itu mungkin berjalan dengan baik.
Thordax
1
Yah, saya benar-benar tidak mengerti maksud saya, maksud saya saya perlu cara untuk segera mendapatkan contoh Fragmen yang sedang ditampilkan, tidak secara iteratif memeriksa semua fragmen dan kemudian memutuskan fragmen mana yang sekarang ditampilkan di layar.
Leem.fin
11

Nah, pertanyaan ini mendapat banyak pandangan dan perhatian tetapi masih tidak berisi solusi termudah dari saya - menggunakan getFragments ().

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);
Nativ
sumber
1
Sayangnya, ini tidak selalu benar, getSupportFragmentManager().getFragments() memberi Anda kembali daftar tetapi itu dapat menyimpan nilai nol, jika fragmen terbaru baru saja muncul dari backstack. Persamaan: Jika Anda memeriksa jalan Anda di dalam onBackStackChanged()metode dan Anda memanggil popBackStack()suatu tempat, maka itu mCurrentFragmentakan menjadi null.
Stumi
@Stumi Terima kasih atas informasi ini. Yap, terdengar seperti salah satu dari banyak masalah aneh siklus hidup di Android.
Nativ
9

Anda dapat menanyakan fragmen mana yang dimuat ke dalam bingkai konten Aktivitas Anda, dan mengambil kelas fragmen, atau fragmen 'nama sederhana' (sebagai string).

public String getCurrentFragment(){
     return activity.getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();
}

Pemakaian:

Log.d(TAG, getCurrentFragment());

Output:

D/MainActivity: FragOne
Tuan L
sumber
8

Ini agak terlambat, Tetapi bagi siapa saja yang tertarik: Jika Anda mengetahui indeks fragmen yang Anda inginkan di FragmentManager, dapatkan referensi untuk itu dan periksa fungsi isMenuVisible ()! di sini:

getSupportFragmentManager().getFragments().get(0).isMenuVisible()

Jika ini trueterlihat oleh pengguna dan seterusnya!

MohammadReza
sumber
1
Anehnya, ini adalah satu-satunya solusi yang tercantum di sini yang bekerja untuk saya. Pada saat yang sama, beberapa fragmen dapat memiliki isVisible() == true, getView() != null. Plus, dalam kode saya getBackStackEntryCountselalu nol. Meskipun saya tidak menggunakan menu, isMenuVisible()sejauh ini adalah satu-satunya diskriminan yang tampaknya dapat diandalkan untuk fragmen 'aktif' saat ini. ty
parvus
7

1)

ft.replace(R.id.content_frame, fragment, **tag**).commit();

2)

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment currentFragment = fragmentManager.findFragmentById(R.id.content_frame);

3)

if (currentFragment.getTag().equals(**"Fragment_Main"**))
{
 //Do something
}
else
if (currentFragment.getTag().equals(**"Fragment_DM"**))
{
//Do something
}
Nam Ngo Thanh
sumber
6

Jika sampai di sini dan Anda menggunakan Kotlin:

var fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)

R.id.fragment_containeradalah idtempat fragmentpresentasi merekaactivity

Atau jika Anda menginginkan solusi yang lebih baik:

supportFragmentManager.findFragmentById(R.id.content_main)?.let {
    // the fragment exists

    if (it is FooFragment) {
        // The presented fragment is FooFragment type
    }
}
pableiros
sumber
5

Terinspirasi oleh jawaban Tainy , ini dua sen saya. Sedikit dimodifikasi dari sebagian besar implementasi lainnya.

private Fragment getCurrentFragment() {
    FragmentManager fragmentManager = myActivity.getSupportFragmentManager();
    int stackCount = fragmentManager.getBackStackEntryCount();
    if( fragmentManager.getFragments() != null ) return fragmentManager.getFragments().get( stackCount > 0 ? stackCount-1 : stackCount );
    else return null;
}

Ganti "myActivity"dengan "ini" jika itu adalah aktivitas Anda saat ini atau gunakan referensi untuk aktivitas Anda.

Nashe
sumber
5

Ada metode yang disebut findFragmentById()di SupportFragmentManager. Saya menggunakannya dalam wadah aktivitas seperti:

public Fragment currentFragment(){
    return getSupportFragmentManager().findFragmentById(R.id.activity_newsfeed_frame);
}

Itulah cara mendapatkan arus Anda Fragment. Jika Anda memiliki kebiasaan Fragmentdan perlu memeriksa apa Fragmentitu, saya biasanya menggunakan instanceof:

if (currentFragment() instanceof MyFrag){
    // Do something here
}
Kevin Murvie
sumber
5

Jika Anda menggunakan AndroidX Navigation:

val currentFragment = findNavController(R.id.your_navhost).?currentDestination

Untuk info lebih lanjut tentang komponen navigasi ini: https://developer.android.com/guide/navigation/navigation-getting-started

Cory Roy
sumber
Ini tidak dikompilasi
IgorGanapolsky
1
Itu hanya akan dikompilasi jika Anda telah mengatur navigasi AndroidX dengan benar dan entah bagaimana disebut navHost Anda your_navhost.
Cory Roy
4

Ini adalah cara sederhana untuk mendapatkan fragmen saat ini ..

getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
  @Override public void onBackStackChanged() {
    currentFragment = fragmentManager.findFragmentById(R.id.content);
    if (currentFragment !=  null && (currentFragment instanceof LoginScreenFragment)) {
      logout.setVisibility(View.GONE);
    } else {
      logout.setVisibility(View.VISIBLE);
    }
  }
});
lallu Sukendh
sumber
4

Jawaban Sev bekerja ketika Anda menekan tombol kembali atau mengubah backstack.

Saya melakukan sesuatu yang sedikit berbeda. Saya memiliki pengaturan backstack perubahan pendengar pada basis Fragmen dan fragmen yang diturunkan dan kode ini ada di pendengar:

Fragment f = getActivity().getSupportFragmentManager().findFragmentById(R.id.container);

if (f.getClass().equals(getClass())) {
    // On back button, or popBackStack(),
    // the fragment that's becoming visible executes here,
    // but not the one being popped, or others on the back stack

    // So, for my case, I can change action bar bg color per fragment
}
MCLLC
sumber
3

Ini bekerja untuk saya. Saya harap ini akan membantu seseorang.

FragmentManager fragmentManager = this.getSupportFragmentManager();  
        String tag = fragmentManager
                    .getBackStackEntryAt(
                    fragmentManager
                    .getBackStackEntryCount() - 1)
                    .getName();
              Log.d("This is your Top Fragment name: ", ""+tag);
Cüneyt
sumber
3

Jika Anda mendapatkan instance Fragment saat ini dari aktivitas induk, Anda bisa melakukannya

findFragmentByID(R.id.container);

Ini sebenarnya adalah contoh fragmen saat ini yang terisi pada tampilan. Saya memiliki masalah yang sama. Saya harus memuat fragmen yang sama dua kali menjaga satu di backstack.

Metode berikut tidak berfungsi. Itu hanya mendapat Fragmen yang memiliki tag. Jangan buang waktu Anda pada metode ini. Saya yakin ini memiliki kegunaan tetapi untuk mendapatkan versi terbaru dari Fragmen yang sama bukan salah satunya.

findFragmentByTag()
Yasin Yaqoobi
sumber
3

Lihat solusi ini. Ini berhasil bagi saya untuk mendapatkan Fragmen saat ini.

if(getSupportFragmentManager().getBackStackEntryCount() > 0){
        android.support.v4.app.Fragment f = 
         getSupportFragmentManager().findFragmentById(R.id.fragment_container);
        if(f instanceof ProfileFragment){
            Log.d(TAG, "Profile Fragment");
        }else if(f instanceof SavedLocationsFragment){
            Log.d(TAG, "SavedLocations Fragment");
        }else if(f instanceof AddLocationFragment){
            Log.d(TAG, "Add Locations Fragment");
        }
Haroon khan
sumber
2
final FragmentManager fm=this.getSupportFragmentManager();
final Fragment fragment=fm.findFragmentByTag("MY_FRAGMENT");

if(fragment != null && fragment.isVisible()){
      Log.i("TAG","my fragment is visible");
}
else{
      Log.i("TAG","my fragment is not visible");
}
kmarin
sumber
Ini bekerja dengan Jetpack?
IgorGanapolsky
2
getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();

Yah, saya kira ini adalah jawaban yang paling mudah untuk pertanyaan ini. Saya harap ini membantu.

Abhishek
sumber
2

Berikut ini adalah solusi Kotlin:

if ( this.getSupportFragmentManager().getBackStackEntryCount()>0 ) {
    var fgmt = this.getSupportFragmentManager().fragments[this.getSupportFragmentManager().getBackStackEntryCount()-1]
    if( fgmt is FgmtClassName ) {
        (fgmt as FgmtClassName).doSth()
    }
}

Cara yang disederhanakan:

with ( this.getSupportFragmentManager() ) {
    if ( getBackStackEntryCount()>0 ) {
        var fgmt = fragments[getBackStackEntryCount()-1]
        if ( fgmt is FgmtClassName ) {
            (fgmt as FgmtClassName).doSth()
        }
    }
}
Anamkin
sumber
2

Cara mudah untuk melakukannya:

Fragment fr=getSupportFragmentManager().findFragmentById(R.id.fragment_container);
String fragmentName = fr.getClass().getSimpleName();
Biplob Das
sumber
1

Dalam aktivitas utama, metode onAttachFragment (Fragment fragment) dipanggil ketika fragmen baru dilampirkan ke aktivitas. Dalam metode ini, Anda bisa mendapatkan instance dari fragmen saat ini. Namun, metode onAttachFragment tidak dipanggil ketika sebuah fragmen muncul dari backstack, yaitu, ketika tombol kembali ditekan untuk mendapatkan fragmen atas di atas tumpukan. Saya masih mencari metode panggilan balik yang dipicu dalam aktivitas utama ketika sebuah fragmen menjadi terlihat di dalam aktivitas.

ufdeveloper
sumber
sangat dekat! :-)
Blundell
Kami menggunakan perpustakaan Jetpack Navigation
IgorGanapolsky
1

Dalam kasus fragmen yang digulir, ketika instance penggunaan Anda dari kelas ViewPager, misalkan mVeiwPager, Anda dapat memanggil mViewPager.getCurrentItem () untuk mendapatkan nomor int fragmen saat ini.

di MainLayout.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    tools:context="unidesign.photo360.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="false"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:expanded="false">

        <android.support.v7.widget.Toolbar
            android:id="@+id/main_activity_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            app:title="@string/app_name">

        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>


    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </android.support.v4.view.ViewPager>
    
</android.support.design.widget.CoordinatorLayout>

di MainActivity.kt

class MainActivity : AppCompatActivity() {
    
        lateinit var mViewPager: ViewPager
        lateinit var pageAdapter: PageAdapter
        
//      ...
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            
            pageAdapter = PageAdapter(supportFragmentManager)
            mViewPager = findViewById(R.id.view_pager)
//          ...
            }
            
        override fun onResume() {
          super.onResume()
          var currentFragment = pageAdapter.getItem(mViewPager.currentItem)
//         ...
          }

Andrei Radchenko
sumber
1

Saya menemukan findFragmentByTagtidak nyaman. Jika ada String currentFragmentTagdi Activityatau orang tua FragmentAnda, Anda harus menyimpannya onSaveInstanceStatedan mengembalikannya onCreate. Bahkan jika Anda melakukannya, ketika Activitydiciptakan, onAttachFragmentakan disebut sebelum onCreate, sehingga Anda tidak dapat menggunakan currentFragmentTagdalam onAttachFragment(misalnya. Memperbarui beberapa pandangan berdasarkancurrentFragmentTag ), karena kekuatan itu belum dipulihkan.

Saya menggunakan kode berikut:

Fragment getCurrentFragment() {
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if(fragments.isEmpty()) {
        return null;
    }
    return fragments.get(fragments.size()-1);
}

Dokumen FragmentManagernegara itu

Urutan fragmen dalam daftar adalah urutan di mana mereka ditambahkan atau dilampirkan.

Ketika Anda perlu melakukan hal-hal berdasarkan jenis fragmen saat ini, cukup gunakan getCurrentFragment() instance of MyFragmentsaja currentFragmentTag.equals("my_fragment_tag").

Perhatikan bahwa getCurrentFragment()di onAttachFragmenttidak akan mendapatkan melampirkan tersebut Fragment, tapi yang terpasang sebelumnya.

Jeffrey Chen
sumber
1

Saya harus melakukan ini baru-baru ini dan tidak ada jawaban di sini yang cocok dengan skenario ini.

Jika Anda yakin hanya satu fragmen yang akan terlihat (layar penuh), maka sangat ingin menemukan apa yang ada di bagian atas backstack. Misalnya, sebagai Kotlinuntuk Fragment:

import androidx.fragment.app.Fragment

fun Fragment.setVisibilityChangeListener(clazz: Class<out Fragment>, listener: (Boolean) -> Unit) {
    fragmentManager?.run {
        addOnBackStackChangedListener {
            val topFragmentTag = getBackStackEntryAt(backStackEntryCount - 1).name
            val topFragment = findFragmentByTag(topFragmentTag)
            listener(topFragment != null && topFragment::class.java == clazz)
        }
    }
}

Dan gunakan seperti:

class MyFragment: Fragment {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        setVisibilityChangeListener(this::class.java) { visible -> 
            // Do stuff
        }
    }
}
Mikel Pascual
sumber
1

Anda dapat melakukannya dengan sangat mudah juga dengan URL di logcat yang akan mengarahkan Anda ke kode sumber kode sumber fragmen saat ini. Pertama, Anda perlu menambahkan OnBackStackChangedListener dalam aktivitas host seperti -

activity.getChildFragmentManager().addOnBackStackChangedListener(backStackListener);

Dan implementasi OnBackStackChangedListener adalah -

    public FragmentManager.OnBackStackChangedListener backStackListener = () -> {

    String simpleName = "";
    String stackName = getStackTopName().trim();

    if (Validator.isValid(stackName) && stackName.length() > 0) {

      simpleName = stackName.substring(Objects.requireNonNull(stackName).lastIndexOf('.') + 1).trim();

      List<Fragment >
       fragmentList = getChildFragmentManager().getFragments();
      Fragment myCurrentFragment;

      for (int i = 0; i < fragmentList.size(); i++) {
       myCurrentFragment= fragmentList.get(i);
       if (myCurrentFragment.getClass().getSimpleName().equals(simpleName)) {
        //Now you get the current displaying fragment assigned in myCurrentFragment.
        break;
       }
       myFragment = null;
      }
     }


     //The code below is for the source code redirectable logcat which would be optional for you.
     StackTraceElement stackTraceElement = new StackTraceElement(simpleName, "", simpleName + ".java", 50);
     String fileName = stackTraceElement.getFileName();
     if (fileName == null) fileName = "";
     final String info = "Current Fragment is:" + "(" + fileName + ":" +
     stackTraceElement.getLineNumber() + ")";
     Log.d("now", info + "\n\n");
    };

Dan metode getStackTopName () adalah -

public String getStackTopName() {
    FragmentManager.BackStackEntry backEntry = null;
    FragmentManager fragmentManager = getChildFragmentManager();
    if (fragmentManager != null) {
        if (getChildFragmentManager().getBackStackEntryCount() > 0)
            backEntry = getChildFragmentManager().getBackStackEntryAt(
                    getChildFragmentManager().getBackStackEntryCount() - 1
            );
    }
    return backEntry != null ? backEntry.getName() : null;
}
Gk Mohammad Emon
sumber