Kann die neue Navigationsarchitekturkomponente mit DialogFragment verwendet werden? Muss ich einen benutzerdefinierten Navigator erstellen?
Ich würde sie gerne mit den neuen Funktionen in meinem Navigationsdiagramm verwenden.
Leonardo Deleon
Kann die neue Navigationsarchitekturkomponente mit DialogFragment verwendet werden? Muss ich einen benutzerdefinierten Navigator erstellen?
Ich würde sie gerne mit den neuen Funktionen in meinem Navigationsdiagramm verwenden.
MatPag
Aktualisierung Mai 2019:
DialogFragment werden jetzt ab vollständig unterstützt
Navigation 2.1.0
können Sie mehr lesen hier und hier
Alte Antwort für Navigation <= 2.1.0-alpha02:
Ich bin so vorgegangen:
1) Aktualisieren Navigation
Bibliothek mindestens bis zur Version 2.1.0-alpha01
und kopiere beide Dateien davon modifizierter Kern in Ihrem Projekt.
2) Ändern Sie dann in Ihrem Navigationshostfragment die name
Parameter nach Ihren Wünschen NavHostFragment
<fragment
android:id="@+id/nav_host_fragment"
android:name="com.example.app.navigation.MyNavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" />
3) Erstelle dein DialogFragment
Unterklassen und fügen Sie sie Ihrer hinzu nav_graph.xml
mit:
<dialog
android:id="@+id/my_dialog"
android:name="com.example.ui.MyDialogFragment"
tools:layout="@layout/my_dialog" />
4) Starten Sie sie jetzt aus Fragmenten oder Aktivitäten mit
findNavController().navigate(R.id.my_dialog)
oder ähnliche Methoden.
Ich habe es mit der letzten Version versucht und es funktioniert, aber Animationen laufen nicht für mich. Ich muss sie in der Dialogklasse setzen. Geht das jemandem auch so?
– JSR – Silicornio
21. Mai 2019 um 17:19 Uhr
Wie man mit seinem Positiv- und Negativ-Klick-Listener umgeht.
– Pinakin Kansara
22. Juli 2019 um 9:32 Uhr
@Pinakin Sie handhaben Ergebnisse direkt in Ihrem Benutzerkonto DialogFragment
zum Beispiel mit der onCreateDialog
und Einstellung a setPositiveButton
und setNegativeButton
Zuhörer
– MatPag
9. März 2020 um 16:54 Uhr
kann ich das für TimePickerFragment implementieren?
– Rizki Oktavia Ningrum
13. April 2020 um 1:50 Uhr
@Pinakin Wenn Sie die Navigation verwenden, um zu einem Dialogfragment zu gelangen, stellen Sie sich das so vor, als würden Sie zu einem anderen Fragment navigieren. Wie würden Sie ein Ergebnis zurückbekommen, wenn Sie zu einem regulären Fragment navigieren? developer.android.com/training/basics/fragments/… Wenn der Dialog dem Fragment gehört, das ihn gestartet hat, und Sie Click-Listener wünschen, ist die Verwendung von a möglicherweise besser Dialog
und Navigation überspringen.
– Viktor Rendina
29. Juli 2020 um 12:50 Uhr
Nein, ab dem 1.0.0-alpha01
build, gibt es keine Unterstützung für Dialoge als Teil Ihres Navigationsdiagramms. Sie sollten einfach weiter verwenden Show() ein zeigen DialogFragment
.
Funktionsanfragen für die Navigation können an die gerichtet werden öffentlicher Issue-Tracker – Stellen Sie sicher, dass Sie Ihren Anwendungsfall angeben und warum Sie Dialoge in Ihrem Navigationsdiagramm nützlich finden würden.
– ianhanniballake
13. Mai 2018 um 0:34 Uhr
Gibt es seit dem Frühjahr eine Aktualisierung des Plans für Dialoge?
– Adam Hurwitz
23. August 2018 um 19:34 Uhr
@AdamHurwitz – Fühlen Sie sich frei, die zu staren bestehendes Problem für Aktualisierungen.
– ianhanniballake
23. August 2018 um 20:16 Uhr
Akzeptierte Antwort ist nicht mehr gültig als DialogFragment
wird jetzt mit unterstützt 2.1.0-alpha03
Ausführung
– Musooff
3. August 2019 um 15:45 Uhr
Sie müssen nur Ihr DialogFragment in NavGraph als Antwort von Razor unten ändern!
– Andy
23. Oktober 2020 um 15:29 Uhr
Allan Veloso
Ja. Das Framework ist so gemacht, dass Sie eine Klasse erstellen können, die das erweitert Navigator
abstrakte Klasse für die Ansichten, die nicht standardmäßig vorhanden sind, und fügen Sie sie Ihrer hinzu NavController
mit der Methode getNavigatorProvider().addNavigator(Navigator navigator)
Wenn Sie die verwenden NavHostFragment
müssen Sie es auch erweitern, um den benutzerdefinierten Navigator hinzuzufügen, oder einfach Ihren eigenen erstellen MyFragment
umsetzen NavHost
Schnittstelle. Es ist so flexibel, dass Sie Ihre eigenen XML-Parameter mit benutzerdefinierten Attributen erstellen können, die in definiert sind values
, so wie Sie benutzerdefinierte Ansichten erstellen. Etwa so (nicht getestet):
@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()
}
}
}
meine_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>
Das Fragment, das navigiert.
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
}
}
Niyas
Ja, das ist möglich. Sie können über das Dialogfragment auf die Ansicht des übergeordneten Fragments zugreifen, indem Sie anrufen getParentFragment().getView()
. Und nutzen Sie die Ansicht zur Navigation.
Hier ist das Beispiel
Navigation.findNavController(getParentFragment().getView()).navigate(R.id.nextfragment);
STAR_ZERO
Ich habe einen benutzerdefinierten Navigator für DialogFragment erstellt.
Probe ist hier.
(Es ist nur ein Beispiel, daher könnte es ein Problem geben.)
@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
}
}
}
Während die Bibliothek in Alpha ist, ändert sie sich wie verrückt. Diese Implementierung funktioniert in alpha11 nicht mehr.
– Allan Veloso
4. Februar 2019 um 22:04 Uhr
Version 2.1.0-alpha03 wurde veröffentlicht, damit wir endlich DialogFragments verwenden können. Leider habe ich einige Probleme mit dem Backstack, wenn ich abbrechende Dialoge verwende. Wahrscheinlich habe ich eine fehlerhafte Implementierung meiner Dialoge.
[LATER-EDIT] Meine Implementierung war gut, das Problem hängt mit der falschen Dialogzählung für DialogFragmentNavigator zusammen, wie in beschrieben Issue-Tracker
Als Workaround kannst du mal nachschauen auf meine Empfehlung
Während die Bibliothek in Alpha ist, ändert sie sich wie verrückt. Diese Implementierung funktioniert in alpha11 nicht mehr.
– Allan Veloso
4. Februar 2019 um 22:04 Uhr
Rasierer
Aktualisiert für:
implementation "androidx.navigation:navigation-ui-ktx:2.2.0-rc04"
Und in my_nav_graph.xml verwenden
<dialog
android:id="@+id/my_dialog"
android:name="com.example.ui.MyDialogFragment"
tools:layout="@layout/my_dialog" />
Dies ist die aktualisierte und korrekte Lösung! Funktioniert bei mir!
– Andy
23. Oktober 2020 um 15:27 Uhr