Sebelum mencoba komponen Navigasi, saya biasa melakukan transaksi fragmen secara manual dan menggunakan tag fragmen untuk mengambil fragmen saat ini.
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
Sekarang di layout aktivitas utama saya, saya memiliki sesuatu seperti:
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nav_host"
app:navGraph= "@navigation/nav_item"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost= "true"
/>
Bagaimana cara mendapatkan kembali fragmen yang ditampilkan saat ini oleh komponen Navigasi? Perbuatan
supportFragmentManager.findFragmentById(R.id.nav_host)
mengembalikan a NavHostFragment
dan saya ingin mengambil 'MyFragment` yang ditampilkan.
Terima kasih.
onActivityResult
aktivitas utama saya. Karena saya tidak bisa mendapatkan fragmen, saya cukup memindahkan semua ini ke dalam fragmen itu sendiri dan sepertinya berhasil.Jawaban:
Saya berhasil menemukan cara untuk saat ini dan itu adalah sebagai berikut:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host); navHostFragment.getChildFragmentManager().getFragments().get(0);
Dalam kasus tentu saja Anda tahu itu adalah fragmen pertama. Saya masih menyelidiki cara tanpa ini. Saya setuju ini bukan cara terbaik tetapi itu harus menjadi sesuatu untuk saat ini.
sumber
navHostFragment!!.childFragmentManager.fragments.any { it.javaClass == fragmentClass && it.isVisible }
Bekerja sangat mirip. Semoga bisa membantu siapa pun!Tidak ada cara yang dapat saya temukan untuk mengambil instance fragmen saat ini. Namun, Anda bisa mendapatkan ID dari fragmen yang terakhir ditambahkan menggunakan kode di bawah ini.
navController.currentDestination?.getId()
Ini mengembalikan ID dalam file navigasi. Semoga ini membantu.
sumber
Anda harus melihat properti childFragmentManager primaryNavigationFragment dari fragmen nav Anda, di sinilah fragmen yang ditampilkan saat ini direferensikan.
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment) navHost?.let { navFragment -> navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment-> //DO YOUR STUFF } } }
sumber
Ini sepertinya solusi terbersih. Pembaruan: Fungsi ekstensi diubah menjadi properti. Terima kasih Igor Wojda .
1. Buat ekstensi berikut
import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager val FragmentManager.currentNavigationFragment: Fragment? get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2. Dalam
Activity
denganNavHostFragment
penggunaan seperti ini:val currentFragment = supportFragmentManager.currentNavigationFragment
sumber
FragmentManager.currentNavigationFragment
(bukan sebagai fungsi)Gunakan
addOnDestinationChangedListener
dalam aktivitas memilikiNavHostFragment
Untuk Java
NavController navController= Navigation.findNavController(MainActivity.this,R.id.your_nav_host); navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() { @Override public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) { Log.e(TAG, "onDestinationChanged: "+destination.getLabel()); } });
Untuk Kotlin
var navController :NavController=Navigation.findNavController(this, R.id.nav_host_fragment) navController.addOnDestinationChangedListener { controller, destination, arguments -> Log.e(TAG, "onDestinationChanged: "+destination.label); }
sumber
ini mungkin terlambat tetapi bagi siapa saja yang masih melihat
val currentFragment = NavHostFragment.findNavController(nav_host_fragment).currentDestination?.id
maka Anda dapat melakukan sesuatu seperti
if(currentFragment == R.id.myFragment){ //do something }
perhatikan bahwa ini untuk kotlin, kode java harus hampir sama
sumber
navController().currentDestination?.id
akan memberi Anda
Fragment
id Anda saat ini di manaprivate fun navController() = Navigation.findNavController(this, R.id.navHostFragment)
id ini adalah id yang telah Anda berikan di
Navigation Graph XML
file Anda di bawahfragment
tag. Anda juga bisa membandingkancurrentDestination.label
jika Anda mau.sumber
Menemukan solusi yang berfungsi.
private fun getCurrentFragment(): Fragment? { val currentNavHost = supportFragmentManager.findFragmentById(R.id.nav_host_id) val currentFragmentClassName = ((this as NavHost).navController.currentDestination as FragmentNavigator.Destination).className return currentNavHost?.childFragmentManager?.fragments?.filterNotNull()?.find { it.javaClass.name == currentFragmentClassName } }
sumber
Dari Aktivitas yang menggunakan
NavHostFragment
, Anda dapat menggunakan kode di bawah ini untuk mengambil instance dariActive Fragment
.val fragmentInstance = myNavHostFragment?.childFragmentManager?.primaryNavigationFragment
sumber
Persyaratan saya adalah mendapatkan fragmen yang terlihat saat ini dari aktivitas Induk, solusi saya adalah
private LoginFragment getCurrentVisibleFragment() { NavHostFragment navHostFragment = (NavHostFragment)getSupportFragmentManager().getPrimaryNavigationFragment(); FragmentManager fragmentManager = navHostFragment.getChildFragmentManager(); Fragment loginFragment = fragmentManager.getPrimaryNavigationFragment(); if(loginFragment instanceof LoginFragment){ return (LoginFragment)loginFragment; } return null; }
Ini dapat membantu seseorang dengan masalah yang sama.
sumber
Sesuai jawaban dan komentar @slhddn, inilah cara saya menggunakannya dan mengambil id fragmen dari file nav_graph.xml :
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setSupportActionBar(findViewById(R.id.toolbar)) val navController = findNavController(this, R.id.nav_host_fragment) ivSettingsCog.setOnClickListener { if (navController.currentDestination?.id == R.id.updatesFragment) // Id as per set up on nav_graph.xml file { navController.navigate(R.id.action_updatesFragment_to_settingsFragment) } } } }
sumber
dapatkah Anda
getChildFragmentManager()
menghubungi dengansumber
Buat:
• di beberapa tombol di fragmen Anda:
val navController = findNavController(this) navController.popBackStack()
• Dalam Aktivitas Anda onBackPressed ()
override fun onBackPressed() { val navController = findNavController(R.id.nav_host_fragment) val id = navController.currentDestination?.getId() if (id == R.id.detailMovieFragment){ navController.popBackStack() return } super.onBackPressed() }
sumber
Jika Anda membutuhkan instance dari fragmen Anda, Anda dapat menggunakan:
(Aktivitas) =>
supportFragmentManager.fragments.first().childFragmentManager.fragments.first()
Ini sangat jelek tetapi dari sana Anda dapat memeriksa apakah itu adalah instance dari fragmen yang ingin Anda mainkan
sumber
Di Androidx, saya telah mencoba banyak metode untuk menemukan fragmen yang dibutuhkan
NavHostFragment
. Akhirnya saya bisa memecahkannya dengan metode di bawah inipublic Fragment getFunctionalFragment (String tag_name) { NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment); FragmentManager navHostManager = Objects.requireNonNull(navHostFragment).getChildFragmentManager(); Fragment fragment=null; List fragment_list = navHostManager.getFragments(); for (int i=0; i < fragment_list.size() ; i ++ ) { if ( fragment_list.get(i) instanceof HomeFragment && tag_name.equals("frg_home")) { fragment = (HomeFragment) fragment_list.get(i); break; } } return fragment; }
sumber
Fragmen pertama dalam fragmen navhost adalah fragmen saat ini
Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment(); if (navHostFragment != null) {Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);}
sumber
Pertama, Anda mendapatkan fragmen saat ini berdasarkan id, lalu Anda dapat menemukan fragmen tersebut, bergantung pada id itu.
int id = navController.getCurrentDestination().getId(); Fragment fragment = getSupportFragmentManager().findFragmentById(id);
sumber
Saya menggabungkan jawaban Andrei Toaders dan jawaban Mukul Bhardwajs dengan
OnBackStackChangedListener
.Sebagai atribut:
private FooFragment fragment;
Dalam saya
onCreate
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host); FragmentManager navHostManager = Objects.requireNonNull(navHostFragment).getChildFragmentManager(); FragmentManager.OnBackStackChangedListener listener = () -> { List<Fragment> frags = navHostManager.getFragments(); if(!frags.isEmpty()) { fragment = (FooFragment) frags.get(0); } }; navController.addOnDestinationChangedListener((controller, destination, arguments) -> { if(destination.getId()==R.id.FooFragment){ navHostManager.addOnBackStackChangedListener(listener); } else { navHostManager.removeOnBackStackChangedListener(listener); fragment = null; } });
Dengan cara ini saya bisa mendapatkan sebuah fragmen, yang akan ditampilkan nanti. Seseorang bahkan mungkin dapat melakukan loop
frags
dan memeriksa beberapa fragmen denganinstanceof
.sumber
Saya perlu melakukan ini untuk menyiapkan tampilan navigasi bawah dan saya melakukannya dengan cara ini:
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home) val bottomNavBar: BottomNavigationView = nav_content_view NavigationUI.setupWithNavController(bottomNavBar, navController)
sumber
Cara terbaik untuk melakukannya adalah dengan mendaftarkan callback siklus proses fragmen .
Sesuai pertanyaan awal, jika Anda
NavHostFragment
didefinisikan sebagai ...<fragment android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/nav_host" app:navGraph= "@navigation/nav_item" android:name="androidx.navigation.fragment.NavHostFragment" app:defaultNavHost= "true" />
Kemudian dalam aktivitas utama Anda
onCreate(..)
...nav_host.childFragmentManager.registerFragmentLifecycleCallbacks( object:FragmentManager.FragmentLifecycleCallbacks() { override fun onFragmentViewCreated( fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle? ) { // callback method always called whenever a // fragment is added, or, a back-press returns // to the start-destination } } )
Metode panggilan balik lainnya mungkin diganti agar sesuai dengan kebutuhan Anda.
sumber
Solusi ini akan berfungsi di banyak situasi. Coba ini:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment?.parentFragment as MainFragment
atau ini:
val mainFragment = fragmentManager?.primaryNavigationFragment?.parentFragment as MainFragment
sumber
Kode ini bekerja dari saya
NavDestination current = NavHostFragment.findNavController(getSupportFragmentManager().getPrimaryNavigationFragment().getFragmentManager().getFragments().get(0)).getCurrentDestination(); switch (current.getId()) { case R.id.navigation_saved: // WRITE CODE break; }
sumber
Ini berhasil untuk saya
(navController.currentDestination as FragmentNavigator.Destination).className
Ini akan mengembalikan
canonicalName
fragmen Andasumber
ini mungkin terlambat tetapi dapat membantu seseorang nanti.
jika Anda menggunakan navigasi bersarang, Anda bisa mendapatkan id seperti ini di Kotlin
val nav = Navigation.findNavController(requireActivity(), R.id.fragment_nav_host).currentDestination
dan ini adalah salah satu fragmen di fragment_nav_host.xml
<fragment android:id="@+id/sampleFragment" android:name="com.app.sample.SampleFragment" android:label="SampleFragment" tools:layout="@layout/fragment_sample" />
dan Anda dapat memeriksa semua yang Anda butuhkan seperti ini
if (nav.id == R.id.sampleFragment || nav.label == "SampleFragment"){}
sumber
Akhirnya solusi kerja untuk Anda yang masih mencari. Sebenarnya sangat sederhana dan Anda dapat melakukannya dengan menggunakan callback.
ikuti langkah ini:
Buat listener di dalam fragmen yang Anda inginkan untuk mendapatkan instance dari aktivitas onCreate ()
public class HomeFragment extends Fragment { private OnCreateFragment createLIstener; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { createLIstener.onFragmentCreated(this); View root = inflater.inflate(R.layout.fragment_home, container, false); //findViews(root); return root; } @Override public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.menu_main, menu); } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (item.getItemId()==R.id.action_show_filter){ //do something } return super.onOptionsItemSelected(item); } @Override public void onAttach(Context context) { super.onAttach(context); try { createLIstener = (OnCreateFragment) context; } catch (ClassCastException e) { throw new ClassCastException(context.toString() + " must implement OnArticleSelectedListener"); } } public interface OnCreateFragment{ void onFragmentCreated(Fragment f); } }
Implementasikan listener Anda di Fragment / Activity host
public class MainActivity extends AppCompatActivity implements HomeFragment.OnCreateFragment { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BottomNavigationView navView = findViewById(R.id.nav_view); // Passing each menu ID as a set of Ids because each // menu should be considered as top level destinations. AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder( R.id.navigation_home, R. ----) .build(); NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment); NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); NavigationUI.setupWithNavController(navView, navController); } @Override public void onFragmentCreated(Fragment f) { if (f!=null){ H.debug("fragment created listener: "+f.getId()); f.setHasOptionsMenu(true); }else { H.debug("fragment created listener: NULL"); } } }
Dan itu semua yang Anda butuhkan untuk melakukan pekerjaan itu. Berharap ini membantu seseorang
sumber
Cara terbaik yang bisa saya ketahui dengan 1 fragmen, Kotlin, penggunaan Navigasi:
Pada file tata letak Anda, tambahkan tag: "android: tag =" main_fragment_tag ""
<fragment android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/nav_host" app:navGraph= "@navigation/nav_item" android:tag="main_fragment_tag" android:name="androidx.navigation.fragment.NavHostFragment" app:defaultNavHost= "true" />
Pada Aktivitas Anda:
val navHostFragment = supportFragmentManager.findFragmentByTag("main_fragment_tag") as NavHostFragment val mainFragment = navHostFragment.childFragmentManager.fragments[0] as MainFragment mainFragment.mainFragmentMethod()
sumber
val fragment: YourFragment? = yourNavHost.findFragment()
Catatan:
findFragment
fungsi ekstensi terletak di dalamandroidx.fragment.app
paket, dan itu adalah fungsi generiksumber
Dalam aktivitas Anda, tentukan objek fragmen. Dan dari setiap fragmen, panggil metode ini dengan meneruskan objek fragmen, seperti Jadi objek fragmen statis akan diganti dengan fragmen yang ditampilkan saat ini setiap saat.
//method in MainActivity private static Fragment fragment; public void setFragment(Fragment fragment){ this.fragment = fragment; } //And from your fragment class, you can call ((<yourActivity in which fragment present>)getActivity()).setFragment(<your fragment object>); //if you want to set it directly; ((<yourActivity in which fragment present>)getActivity()).fragment=<your fragment object>;
Anda juga bisa menyetel callback dari fragmen ke aktivitas, untuk pendekatan yang lebih baik dan meneruskan objek fragmen Anda saat ini.
sumber