Компонент архитектуры навигации - фрагменты диалога - PullRequest
0 голосов
/ 13 мая 2018

Можно ли использовать новый компонент архитектуры навигации с DialogFragment?Нужно ли создавать собственный навигатор?

Я бы хотел использовать их с новыми функциями в моем графике навигации.

Ответы [ 8 ]

0 голосов
/ 13 мая 2019

Да, это возможно сейчас.В первоначальном выпуске это было невозможно, но теперь из "androidx.navigation: navigation-фрагмент: 2.1.0-alpha03" этой версии навигации вы можете использовать фрагмент диалога в компоненте навигации.

Проверьте это: - Поддержка фрагмента диалога Naviagtion

0 голосов
/ 20 марта 2019

Май 2019 Обновление :

DialogFragment теперь полностью поддерживается, начиная с Navigation 2.1.0-alpha03, вы можете прочитать подробнее здесь и здесь

Старый ответ для навигации <= 2.1.0-alpha02: </strong>

Я поступил следующим образом:

1) Обновите Navigation библиотеку как минимум до версии 2.1.0-alpha01 и скопируйте оба файла этой измененной сущности в ваш проект.

3) Затемво фрагменте хоста навигации измените параметр name на свой 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) Создайте свои подклассы DialogFragment и добавьте их в nav_graph.xml с помощью:

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

5) Теперь запустите их из фрагментов или действий с помощью

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

или аналогичных методов.

0 голосов
/ 13 мая 2019

Выпущена версия 2.1.0-alpha03 , поэтому мы наконец можем использовать DialogFragments. К сожалению для меня, у меня есть некоторые проблемы с backstack при использовании отменяемых диалогов. Возможно, у меня неправильная реализация моих диалогов ..

[LATER-EDIT] Моя реализация была хорошей, проблема связана с неправильным подсчетом диалогов для DialogFragmentNavigator, как описано в трекере проблем В качестве обходного пути вы можете посмотреть по моей рекомендации

0 голосов
/ 23 февраля 2019

Один из вариантов - просто использовать обычный фрагмент и сделать его похожим на диалог.Я обнаружил, что это не стоило хлопот, поэтому я использовал стандартный способ, используя show ().Если вы настаиваете Смотрите здесь , как это сделать.

0 голосов
/ 05 февраля 2019

Да .Фреймворк сделан таким образом, что вы можете создать класс, расширяющий абстрактный класс Navigator для представлений, которые не выходят из коробки, и добавить его к вашему NavController с помощью метода getNavigatorProvider().addNavigator(Navigator navigator)* 1006.*

Если вы используете NavHostFragment, вам также потребуется расширить его, чтобы добавить пользовательский Навигатор или просто создать собственный MyFragment, реализующий интерфейс NavHost.Он настолько гибок, что вы можете создавать свои собственные параметры xml с помощью пользовательских атрибутов, определенных в values, так же, как вы создаете собственные представления.Примерно так (не проверено):

@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()
        }
    }
}

Использование

my_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>    

Фрагмент, по которому будет осуществляться навигация.

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 голосов
/ 22 декабря 2018

Да, это возможно. Вы можете получить доступ к представлению родительского фрагмента из фрагмента диалога, вызвав getParentFragment (). GetView (). И используйте вид для навигации.

Вот пример

Navigation.findNavController(getParentFragment().getView()).navigate(R.id.nextfragment);
0 голосов
/ 08 октября 2018

Я создал собственный навигатор для DialogFragment.

Образец здесь .
(Это всего лишь пример, поэтому могут возникнуть проблемы.)

@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
        }
    }
}
0 голосов
/ 13 мая 2018

Нет, в сборке 1.0.0-alpha01 диалоги как часть вашего навигационного графика не поддерживаются. Вы должны просто продолжать использовать show () , чтобы показать DialogFragment.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...