12

I have no idea how to, using the new navigation architecture component, navigate from my main screen (with a FloatingActionButton attatched to a BottomAppBar) to another screen without the app bar.

When I click the fab I want my next screen (fragment?) to slide in from the right. The problem is where do I put my BottomAppBar? If I put it in my MainActivity then I have the issue of the FloatingActionButton not having a NavController set. I also cannot put my BottomAppBar in my Fragment. I am at a loss.

Charlie Niekirk
  • 790
  • 7
  • 13

5 Answers5

24

Ran into this issue today and I found out that there is a simple and elegant solution for it.

val navController = findNavController(R.id.navHostFragment)

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

This takes care of the navigation. Then you must control the visibility of your BottomAppBar inside your Activity.

Dariush Malek
  • 804
  • 1
  • 5
  • 12
5

You could have your BottomAppBar in MainActivity and access your FloatingActionButton in your fragment as follows

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

You could hide the BottomAppBar from another activity as follows

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

Make sure you .show() the BottomAppBar while returning to previous fragment

Yaswant Narayan
  • 1,157
  • 1
  • 12
  • 20
1

Put it in MainActivity and setOnClickListener in onStart() of the activity and it will work fine.

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

Note:This solution is like and hack and better is to follow Activity LifeCycle and setUp OnClickListener when the activity is ready to interact.

Similar question [SOLVED]

Anmol
  • 5,619
  • 3
  • 28
  • 54
1

if you wanted to navigate to certain fragment (not the star one) in the beginning for some reason, and also you have to graphs for one activity, here is what I suggest: this method will start activity

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

and then in, onCreate method of Host Activity, first decide which graph to use and then pass the intent extras bundle so the start fragment can decide what to do:

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

and here's how you can decide what to do in start fragment:

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

and then navigate like you would do normally:

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

here's how your graph might look in case you wanted to jump to the third fragment in the beginning enter image description here

PS: make sure you will handle back button on the third fragment, here's a solution

UPDATE: as EpicPandaForce mentioned, you can also start activities using Navigation Components: to do that, first add the Activity to your existing graph, either by the + icon (which didn't work for me) or by manually adding in the xml:

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

you can also add arguments and use them just like you would in a fragment, with 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>

in koltin,here's how you would use the argument, First declare args with the type of generated class named after you activity, in this case SecondActivityArgs in top of your activity class:

val args: SecondActivityArgsby by navArgs()

and then you can use it like this:

print(args.testArgument)
Amin Keshavarzian
  • 2,335
  • 1
  • 26
  • 28
0

This doesn't destroy BottomAppBar. Add this to MainActivity only and don't do anything else

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

fabAdd.setOnClickListener {
   findNavController(navHostFragment).navigate(R.id.fab)
} 
bakero98
  • 795
  • 4
  • 18