I know it is possible to pass a single argument using Action in the source fragment
override fun onClick(v: View) {
val amountTv: EditText = view!!.findViewById(R.id.editTextAmount)
val amount = amountTv.text.toString().toInt()
val action = SpecifyAmountFragmentDirections.confirmationAction(amount)
v.findNavController().navigate(action)
}
and get that in the destination fragment as specified in android docs
val args: ConfirmationFragmentArgs by navArgs()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val tv: TextView = view.findViewById(R.id.textViewAmount)
val amount = args.amount
tv.text = amount.toString()
}
please let me know is there any way to pass multiple arguments in TypeSafe way
Yes, you could do it by defining multiple arguments for your fragment in the Navigation graph and then pass them to the action
in your code. This is an example:
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/firstFragment">
<fragment
android:id="@+id/firstFragment"
android:name="com.example.app.FirstFragment"
android:label="FirstFragment"
tools:layout="@layout/fragment_first">
<action
android:id="@+id/action_firstFragment_to_secondFragment"
app:destination="@id/secondFragment"
app:enterAnim="@anim/slide_in_right"
app:popExitAnim="@anim/slide_out_left" />
</fragment>
<fragment
android:id="@+id/secondFragment"
android:name="com.example.app.SecondFragment"
android:label="secondFragment"
tools:layout="@layout/fragment_second">
<argument
android:name="firstDataList"
app:argType="com.example.app.domain.FirstData[]" />
<argument
android:name="secondDataList"
app:argType="com.example.app.domain.SecondData[]" />
<argument
android:name="isOkey"
app:argType="boolean" />
<argument
android:name="myString"
app:argType="string" />
</fragment>
</navigation>
and then in your code:
You should pass the arguments respectively as it is navigation.xml
FirstFragment.kt
findNavController().navigate(
FirstFragmentDirections.actionFirstFragmentToSecondFragment(
firstDataList.toTypedArray(),
secondDataList.toTypedArray(),
isOkey,
myString
)
And then retrieve it at the destination as a bundle
like so:
SecondFragment.kt
val args = arguments?.let {
SecondFragmentArgs.fromBundle(
it
)
}
if (args != null) {
firstDataList = args.firstDataList.toCollection(ArrayList())
secondDataList = args.secondDataList.toCollection(ArrayList())
isOkey = args.isOkey
myString = args.myString
}
To pass complex objects you should make them parcelable
. In my example, I passed two lists of complex models that I parcelized them like this:
DataModels.kt
@Parcelize
data class FirstData(var id: Int, var color: Int = 0) : Parcelable
@Parcelize
data class SecondData(var name: String, var position: ArrayList<Int>) : Parcelable