ナビゲーションコンポーネントを試す前に、フラグメントトランザクションを手動で実行し、現在のフラグメントを取得するためにフラグメントタグを使用していました。
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
私のメインアクティビティレイアウトには次のようなものがあります。
<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"
/>
ナビゲーションコンポーネントによって現在表示されているフラグメントを取得するにはどうすればよいですか?やること
supportFragmentManager.findFragmentById(R.id.nav_Host)
NavHostFragment
を返し、表示された 'MyFragment`を取得したい。
ありがとうございました。
私は今のところ方法を発見することができました。それは次のとおりです。
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_Host);
navHostFragment.getChildFragmentManager().getFragments().get(0);
もちろん、それが最初のフラグメントであることを知っています。私はまだこれなしの方法を調査しています。私はそれが最善の方法ではないことに同意しますが、それは今のところ何かであるべきです。
現在のフラグメントインスタンスを取得する方法はありません。ただし、以下のコードを使用して、最後に追加されたフラグメントのIDを取得できます。
navController.getCurrentDestination().getId()
ナビゲーションファイルでIDを返します。お役に立てれば。
NavフラグメントのchildFragmentManager primaryNavigationFragmentプロパティを確認する必要があります。これは、現在表示されているフラグメントが参照される場所です。
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment)
navHost?.let { navFragment ->
navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment->
//DO YOUR STUFF
}
}
}
addOnDestinationChangedListener
を持つアクティビティでNavHostFragment
を使用します
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());
}
});
これは遅いかもしれませんが、まだ探している人のために
val currentfraagment=NavHostFragment.findNavController(nav_Host_fragment).currentDestination!!.id
その後、次のようなことができます
if(currentfraagment == R.id.myFragemnt){
//do something
}
これはkotlin用であり、Javaコードはほぼ同じであることに注意してください
実用的なソリューションが見つかりました。
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
}
}
これは最もクリーンなソリューションのようです。
1。次の拡張子を作成します
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
fun FragmentManager.getCurrentNavigationFragment(): Fragment? =
primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2。Activity
ではNavHostFragment
と一緒に使用します:
val currentFragment = supportFragmentManager.getCurrentNavigationFragment()
getChildFragmentManager()
で確認してください
NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_Host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
まず、IDで現在のフラグメントを取得し、次にそのIDに応じてフラグメントを見つけることができます。
int id = navController.getCurrentDestination().getId();
Fragment fragment = getSupportFragmentManager().findFragmentById(id)l
作る:
•フラグメント内のボタン:
val navController = findNavController(this)
navController.popBackStack()
•アクティビティ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()
}
アクティビティでフラグメントオブジェクトを定義します。そして、各フラグメントから、フラグメントオブジェクトを渡すことでこのメソッドを呼び出します。そのため、静的フラグメントオブジェクトは毎回現在表示中のフラグメントによってオーバーライドされます。
//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>;
より良いアプローチのために、フラグメントからアクティビティにコールバックを設定して、現在のフラグメントオブジェクトを渡すこともできます。
Andrei Toaders answer と Mukul Bhardwajs answer をOnBackStackChangedListener
と組み合わせました。
属性として:
private FooFragment fragment;
私の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;
}
});
このようにして、後で表示されるフラグメントを取得できます。 frags
をループして、instanceof
で複数のフラグメントをチェックすることもできます。
これを達成する最良の方法は、フラグメントライフサイクルコールバックを登録することです。
元の質問によると、NavHostFragment
が次のように定義されている場合...
<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"
/>
次に、メインアクティビティ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
}
}
)
他のコールバックメソッドは、要件に合わせてオーバーライドできます。
下部のナビゲーションビューをセットアップするためにこれを行う必要がありますが、次のようにしました。
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home)
val bottomNavBar: BottomNavigationView = nav_content_view
NavigationUI.setupWithNavController(bottomNavBar, navController)