Est-il possible d'utiliser le nouveau composant d'architecture de navigation avec DialogFragment? Dois-je créer un navigateur personnalisé?
J'aimerais les utiliser avec les nouvelles fonctionnalités de mon graphique de navigation.
Non, à partir de la version 1.0.0-alpha01
, les dialogues ne sont plus pris en charge dans votre graphique de navigation. Vous devriez simplement continuer à utiliser show () pour afficher une DialogFragment
.
Oui, c'est possible. Vous pouvez accéder à la vue du fragment parent à partir du fragment de dialogue en appelant getParentFragment (). GetView (). Et utilisez la vue pour la navigation.
Voici l'exemple
Navigation.findNavController(getParentFragment().getView()).navigate(R.id.nextfragment);
J'ai créé un navigateur personnalisé pour DialogFragment.
Échantillon est ici .
(C'est juste un échantillon, donc ça pourrait être n'importe quel problème.)
@Navigator.Name("dialog_fragment")
class DialogNavigator(
private val fragmentManager: FragmentManager
) : Navigator<DialogNavigator.Destination>() {
companion object {
private const val TAG = "dialog"
}
override fun navigate(destination: Destination, args: Bundle?,
navOptions: NavOptions?, navigatorExtras: Extras?) {
val fragment = destination.createFragment(args)
fragment.setTargetFragment(fragmentManager.primaryNavigationFragment,
SimpleDialogArgs.fromBundle(args).requestCode)
fragment.show(fragmentManager, TAG)
dispatchOnNavigatorNavigated(destination.id, BACK_STACK_UNCHANGED)
}
override fun createDestination(): Destination {
return Destination(this)
}
override fun popBackStack(): Boolean {
return true
}
class Destination(
navigator: Navigator<out NavDestination>
) : NavDestination(navigator) {
private var fragmentClass: Class<out DialogFragment>? = null
override fun onInflate(context: Context, attrs: AttributeSet) {
super.onInflate(context, attrs)
val a = context.resources.obtainAttributes(attrs,
R.styleable.FragmentNavigator)
a.getString(R.styleable.FragmentNavigator_Android_name)
?.let { className ->
fragmentClass = parseClassFromName(context, className,
DialogFragment::class.Java)
}
a.recycle()
}
fun createFragment(args: Bundle?): DialogFragment {
val fragment = fragmentClass?.newInstance()
?: throw IllegalStateException("fragment class not set")
args?.let {
fragment.arguments = it
}
return fragment
}
}
}
Oui . La structure est conçue de sorte que vous puissiez créer une classe étendant la classe abstraite Navigator
pour les vues qui ne sortent pas de la boîte et l'ajouter à votre NavController
avec la méthode getNavigatorProvider().addNavigator(Navigator navigator)
.
Si vous utilisez la variable NavHostFragment
, vous devrez également l'étendre pour ajouter le navigateur personnalisé ou simplement créer votre propre interface MyFragment
mettant en œuvre NavHost
. Il est si flexible que vous pouvez créer vos propres paramètres xml avec des attributs personnalisés définis dans values
, comme pour la création de vues personnalisées. Quelque chose comme ça (non testé):
@Navigator.Name("dialog-fragment")
class DialogFragmentNavigator(
val context: Context,
private val fragmentManager: FragmentManager
) : Navigator<DialogFragmentNavigator.Destination>() {
override fun navigate(destination: Destination, args: Bundle?,
navOptions: NavOptions?, navigatorExtras: Extras?
): NavDestination {
val fragment = Class.forName(destination.name).newInstance() as DialogFragment
fragment.show(fragmentManager, destination.id.toString())
return destination
}
override fun createDestination(): Destination = Destination(this)
override fun popBackStack() = fragmentManager.popBackStackImmediate()
class Destination(navigator: DialogFragmentNavigator) : NavDestination(navigator) {
// The value of <dialog-fragment app:name="com.example.MyFragmentDialog"/>
lateinit var name: String
override fun onInflate(context: Context, attrs: AttributeSet) {
super.onInflate(context, attrs)
val a = context.resources.obtainAttributes(
attrs, R.styleable.FragmentNavigator
)
name = a.getString(R.styleable.FragmentNavigator_Android_name)
?: throw RuntimeException("Error while inflating XML. " +
"`name` attribute is required")
a.recycle()
}
}
}
mon_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/navigation"
app:startDestination="@id/navigation_home">
<fragment
Android:id="@+id/navigation_assistant"
Android:name="com.example.ui.HomeFragment"
tools:layout="@layout/home">
<action
Android:id="@+id/action_nav_to_dialog"
app:destination="@id/navigation_dialog" />
</fragment>
<dialog-fragment
Android:id="@+id/navigation_dialog"
Android:name="com.example.ui.MyDialogFragment"
tools:layout="@layout/my_dialog" />
</navigation>
Le fragment qui va naviguer.
class HomeFragment : Fragment(), NavHost {
private val navControllerInternal: NavController by lazy(LazyThreadSafetyMode.NONE){
NavController(context!!)
}
override fun getNavController(): NavController = navControllerInternal
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Built-in navigator for `fragment` XML tag
navControllerInternal.navigatorProvider.addNavigator(
FragmentNavigator(context!!, childFragmentManager, this.id)
)
// Your custom navigator for `dialog-fragment` XML tag
navControllerInternal.navigatorProvider.addNavigator(
DialogFragmentNavigator(context!!, childFragmentManager)
)
navControllerInternal.setGraph(R.navigation.my_navigation)
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
val view = inflater.inflate(R.layout.home)
view.id = this.id
view.button.setOnClickListener{
getNavController().navigate(R.id.action_nav_to_dialog)
}
return view
}
}
Une option consisterait simplement à utiliser un fragment régulier et à lui donner l’apparence d’un dialogue. J'ai trouvé que ça ne valait pas la peine, alors j'ai utilisé la méthode standard en utilisant show (). Si vous insistez Voir ici pour une façon de le faire.