Можно ли использовать новый компонент архитектуры навигации с помощью диалогового окна "Диалог"? Нужно ли создавать пользовательский навигатор?
Я хотел бы использовать их с новыми функциями в моем графике навигации.
Можно ли использовать новый компонент архитектуры навигации с помощью диалогового окна "Диалог"? Нужно ли создавать пользовательский навигатор?
Я хотел бы использовать их с новыми функциями в моем графике навигации.
Нет, с версии 1.0.0-alpha01 нет поддержки диалогов в составе вашего навигационного графика. Вы должны просто продолжать использовать show(), чтобы показать DialogFragment.
Май 2019 Обновление:
DialogFragment теперь полностью поддерживается, начиная с
Navigation 2.1.0-alpha03, вы можете прочитать больше здесь и здесь
Старый ответ для навигации <= 2.1.0-alpha02:
Я поступил так:
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)
или аналогичные методы.
Да, это возможно. Вы можете получить доступ к представлению родительского фрагмента из фрагмента диалога, вызвав getParentFragment(). GetView(). И использовать вид для навигации.
Вот пример
Navigation.findNavController(getParentFragment().getView()).navigate(R.id.nextfragment);
Я создал собственный навигатор для 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
}
}
}
Да Фреймворк сделан таким образом, что вы можете создать класс, расширяющий абстрактный класс Navigator для представлений, которые не выходят из коробки, и добавить его в ваш NavController с помощью метода getNavigatorProvider().addNavigator(Navigator navigator)
Если вы используете NavHostFragment, вам также понадобится расширить его, чтобы добавить пользовательский Navigator или просто создать свой собственный 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
}
}
Один из вариантов - просто использовать обычный фрагмент и сделать его похожим на диалог. Я обнаружил, что это не стоило хлопот, поэтому я использовал стандартный способ, используя show(). Если вы настаиваете, посмотрите здесь, как это сделать.
Выпущена версия 2.1.0-alpha03, поэтому мы наконец можем использовать DialogFragments. К сожалению для меня, у меня есть некоторые проблемы с backstack при использовании отменяемых диалогов. Возможно, у меня неправильная реализация моих диалогов..
[ПОСЛЕДНЯЯ РЕДАКТИРОВАТЬ] Моя реализация была хорошей, проблема связана с неправильным подсчетом диалогов для DialogFragmentNavigator, как описано в трекере проблем. В качестве обходного пути вы можете посмотреть мои рекомендации
Да, это возможно сейчас. В первоначальном выпуске это было невозможно, но теперь из "androidx.navigation: navigation-фрагмент: 2.1.0-alpha03" этой версии навигации вы можете использовать фрагмент диалога в компоненте навигации.
Проверьте это: - Поддержка фрагмента диалога Naviagtion