it-swarm.com.de

Komponente der Navigationsarchitektur - Dialogfragmente

Kann die neue Navigationsarchitekturkomponente mit DialogFragment verwendet werden? Muss ich einen benutzerdefinierten Navigator erstellen?

Ich würde sie gerne mit den neuen Funktionen in meiner Navigationsgrafik verwenden.

17
Leonardo Deleon

Nein, seit dem 1.0.0-alpha01-Build gibt es keine Unterstützung für Dialoge als Teil Ihres Navigationsdiagramms. Sie sollten einfach show () verwenden, um eine DialogFragment anzuzeigen.

13
ianhanniballake

Aktualisierung im Mai 2019 :

DialogFragment wird jetzt ab Navigation 2.1.0-alpha03 Vollständig unterstützt. Weitere Informationen finden Sie unter hier und hier

Alte Antwort für Navigation <= 2.1.0-alpha02:

Ich bin so vorgegangen:

1) Aktualisiere die Bibliothek Navigation mindestens auf die Version 2.1.0-alpha01 Und kopiere beide Dateien dieser geänderten Gist in Ihrem Projekt.

3) Ändern Sie dann in Ihrem Navigations-Host-Fragment den Parameter name in Ihren benutzerdefinierten 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" />

4) Erstelle deine DialogFragment Unterklassen und füge sie deinem nav_graph.xml Hinzu mit:

<dialog
    Android:id="@+id/my_dialog"
    Android:name="com.example.ui.MyDialogFragment"
    tools:layout="@layout/my_dialog" />

5) Starten Sie sie nun aus Fragmenten oder Aktivitäten mit

findNavController().navigate(R.id.my_dialog)

oder ähnliche Methoden.

25
MatPag

Ja, es ist möglich. Sie können über das Dialogfragment auf die Ansicht des übergeordneten Fragments zugreifen, indem Sie getParentFragment (). GetView () aufrufen. Und nutzen Sie die Ansicht zur Navigation.

Hier ist das Beispiel

Navigation.findNavController(getParentFragment().getView()).navigate(R.id.nextfragment);
2
Niyas

Version 2.1.0-alpha wurde veröffentlicht, damit wir endlich DialogFragments verwenden können. Leider habe ich bei der Verwendung abbrechbarer Dialoge einige Probleme mit dem Backstack. 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 im Issue Tracker beschrieben. Als Workaround können Sie sich auf meine Empfehlung hin

1
Liviu

Ich habe einen benutzerdefinierten Navigator für DialogFragment erstellt.

Probe ist hier .
(Es ist nur ein Beispiel, daher könnte es ein Problem sein.)

@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
        }
    }
}
1
STAR_ZERO

Ja . Das Framework ist so erstellt, dass Sie eine Klasse erstellen können, die die abstrakte Klasse Navigator für die Ansichten erweitert, die nicht sofort verfügbar sind, und sie mit der Methode getNavigatorProvider().addNavigator(Navigator navigator) Ihrer NavController hinzufügen.

Wenn Sie die Variable NavHostFragment verwenden, müssen Sie sie auch erweitern, um den benutzerdefinierten Navigator hinzuzufügen, oder erstellen Sie einfach Ihre eigene Variable MyFragment, die die Schnittstelle NavHost implementiert. Es ist so flexibel, dass Sie Ihre eigenen XML-Parameter mit benutzerdefinierten Attributen erstellen können, die in values definiert sind, wie Sie auch benutzerdefinierte Ansichten erstellen. So etwas (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()
        }
    }
}

Verwendungszweck

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
    }
}
0
Allan Veloso

Eine Option wäre, einfach ein reguläres Fragment zu verwenden und es einem Dialog ähnlich zu machen. Ich fand, dass es den Aufwand nicht wert war, also benutzte ich die Standardmethode mit show (). Wenn Sie darauf bestehen siehe hier , wie Sie dies tun können.

0
Jeffrey

Ja, das ist jetzt möglich. In der ursprünglichen Version war es nicht möglich, aber ab "androidx.navigation: navigation-fragment: 2.1.0-alpha03" in dieser Navigationsversion können Sie das Dialogfragment in der Navigationskomponente verwenden.

Überprüfen Sie Folgendes: - nterstützung für Naviagtion-Dialogfragmente

0
Deepak Rajput