在 FAB 单击时导航到片段(导航架构组件)

Posted

技术标签:

【中文标题】在 FAB 单击时导航到片段(导航架构组件)【英文标题】:Navigate to fragment on FAB click (Navigation Architecture Components) 【发布时间】:2018-12-07 16:10:40 【问题描述】:

我不知道如何使用新的导航架构组件从我的主屏幕(带有FloatingActionButton 附加到BottomAppBar)导航到另一个屏幕没有应用栏。

当我单击晶圆厂时,我希望我的下一个屏幕(片段?)从右侧滑入。问题是我将BottomAppBar 放在哪里?如果我把它放在我的MainActivity 中,那么我会遇到FloatingActionButton 没有设置NavController 的问题。我也不能把我的BottomAppBar 放在我的片段中。我很茫然。

【问题讨论】:

【参考方案1】:

今天遇到这个问题,发现有一个简单而优雅的解决方案。

val navController = findNavController(R.id.navHostFragment)

fabAdd.setOnClickListener 
   navController.navigate(R.id.yourFragment)
  

这负责导航。然后你必须控制BottomAppBarActivity 中的可见性。

【讨论】:

您不需要 Navigation.setViewNavController(fabAdd, navController) 行 - 只有在您想使用 fabAdd.findNavController() 时才需要该行(并且,因为您已经引用了您的 NavController,那是' t 你永远需要做的事情)。 如何更好地了解这个伟大的 API,但它的创造者!感谢 ianhanniballake 提供了很棒的图书馆和您的评论。我会把那条线去掉。 什么是 R.id.navHostFragment? 这导致Type mismatch. Required: Fragment Found: Int【参考方案2】:

您可以在MainActivity 中拥有您的BottomAppBar,并在您的片段中访问您的FloatingActionButton,如下所示

activity?.fab?.setOnClickListener  
    /*...*/
    findNavController().navigate(R.id.action_firstFragment_to_secondFragment, mDataBundle)

您可以将BottomAppBar 隐藏在另一个活动中,如下所示

(activity as AppCompatActivity).supportActionBar?.hide()

确保您在返回上一个片段时.show() BottomAppBar

【讨论】:

【参考方案3】:

把它放在MainActivity中,setOnClickListener在activity的onStart()中,就可以正常工作了。

override fun onStart() 
  super.onStart()
  floatingActionButton.setOnClickListener 
    it.findNavController().navigate(R.id.yourFragment)
   

注意:此解决方案类似于 hack,更好的是在 Activity 准备好交互时遵循 Activity LifeCycle 并设置 OnClickListener。

Similar question [SOLVED]

【讨论】:

【参考方案4】:

如果您出于某种原因想在开始时导航到某个片段(不是星号片段),并且您还必须为一项活动绘制图表,我的建议如下: 此方法将启动活动

companion object 

        const val REQUEST_OR_CONFIRM = "request_or_confirm"
        const val IS_JUST_VIEW = "IS_JUST_VIEW"
        const val MODEL = "model"

        fun open(activity: Activity, isRequestOrConfirm: Boolean, isJustView: Boolean = false, model: DataModel? = null) 
            val intent = Intent(activity, HostActivity::class.java)
            intent.putExtra(REQUEST_OR_CONFIRM, isRequestOrConfirm)
            intent.putExtra(IS_JUST_VIEW, isJustView)
            intent.putExtra(MODEL, model)
            activity.startActivity(intent)
        
    

然后在 Host Activity 的 onCreate 方法中,首先决定使用哪个图,然后传递 Intent Extras 捆绑包,以便起始 Fragment 可以决定做什么:

override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_purchase_nav)
        if (intent.getBooleanExtra(REQUEST_OR_CONFIRM, true)) 
            findNavController(R.id.nav_host_fragment).setGraph(R.navigation.nav_first_scenario, intent.extras)
         else 
            findNavController(R.id.nav_host_fragment).setGraph(R.navigation.nav_second_scenario, intent.extras)
        
    

下面是你如何决定在开始片段中做什么:

if (arguments != null && arguments!!.getBoolean(HostActivity.IS_JUST_VIEW))
    navigateToYourDestinationFrag(arguments!!.getParcelable<DataModel>(HostActivity.MODEL))

然后像往常一样导航:

private fun navigateToYourDestinationFrag(model: DataModel) 
        val action = StartFragmentDirections.actionStartFragmentToOtherFragment(model)
        findNavController().navigate(action)
    

如果您想在一开始就跳转到第三个片段,您的图表可能看起来会是这样

PS:请确保您将处理第三个片段上的后退按钮,here 是一个解决方案

更新: 正如 EpicPandaForce 提到的,您还可以使用导航组件启动活动: 要做到这一点,首先将 Activity 添加到您现有的图表中,或者通过 + 图标(这对我不起作用)或通过手动添加 xml:

 <activity
        android:id="@+id/secondActivity"
        tools:layout="@layout/activity_second"
        android:name="com.amin.SecondActivity" >
    </activity>

您还可以像在片段中一样添加参数并使用它们,使用 navArgs()

 <activity
        android:id="@+id/secondActivity"
        tools:layout="@layout/activity_second"
        android:name="com.amin.SecondActivity" >
        <argument
            android:name="testArgument"
            app:argType="string"
            android:defaultValue="helloWorld" />
    </activity>

在 koltin 中,您将如何使用参数,首先声明 args 具有以您的活动命名的生成类的类型,在这种情况下,您的活动类顶部的 SecondActivityArgs:

val args: SecondActivityArgsby by navArgs()

然后你可以像这样使用它:

print(args.testArgument)

【讨论】:

我以为您不必再​​手动启动活动了,因为您可以使用ActivityDestination【参考方案5】:

这不会破坏 BottomAppBar。仅将此添加到 MainActivity,不要做任何其他事情

val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment

fabAdd.setOnClickListener 
   findNavController(navHostFragment).navigate(R.id.fab)
 

【讨论】:

以上是关于在 FAB 单击时导航到片段(导航架构组件)的主要内容,如果未能解决你的问题,请参考以下文章

底部应用栏在使用片段导航时向上/向下滑动(导航架构组件)

如何使用新的导航架构组件从扩展 BroadcastReceiver 的类导航到片段

使用导航从工具栏菜单项单击在片段之间传递数据 - Kotlin

如何使用导航架构组件创建 BottomSheetDialogFragment?

当返回到“导航架构组件”中的同一选项卡时,嵌套片段的状态会丢失

导航组件:找不到 NavController