Android Navigation Component : Pass value (arguments) in fragments

佐手、 提交于 2021-02-07 11:27:23

问题


What I have done:

I have created Navigation Drawer Activity, As updated new format of Navigation Drawer Activity, As per new Android architecture, I got it with Navigation Component structure.

The NavigationView code with NavController and NavigationUI as below which is opening fragment when I click on any navigation item.

    DrawerLayout drawer = findViewById(R.id.drawer_layout);
    NavigationView navigationView = findViewById(R.id.nav_view);
    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    mAppBarConfiguration = new AppBarConfiguration.Builder(
            R.id.nav_home, R.id.nav_profile, R.id.nav_privacy_policy,
            R.id.nav_terms, R.id.nav_contact_us, R.id.nav_share, R.id.nav_send)
            .setDrawerLayout(drawer)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(navigationView, navController);

This is for nav_host_fragment:

<fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/mobile_navigation" />

The navigation is happening using this navigation/mobile_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/mobile_navigation"
    app:startDestination="@+id/nav_home">

    <fragment
        android:id="@+id/nav_home"
        android:name="com.sohamerp.marsremedies.fragment.HomeFragment"
        android:label="@string/menu_home"
        tools:layout="@layout/fragment_home" />

    <fragment
        android:id="@+id/nav_profile"
        android:name="com.sohamerp.marsremedies.fragment.ProfileFragment"
        android:label="@string/menu_my_profile"
        tools:layout="@layout/fragment_profile" />

    <fragment
        android:id="@+id/nav_privacy_policy"
        android:name="com.sohamerp.marsremedies.fragment.PrivacyPolicyFragment"
        android:label="@string/menu_privacy_policy"
        tools:layout="@layout/fragment_privacy_policy" />

    <fragment
        android:id="@+id/nav_terms"
        android:name="com.sohamerp.marsremedies.fragment.TermsConditionFragment"
        android:label="@string/menu_terms"
        tools:layout="@layout/fragment_terms_condition" />

    <fragment
        android:id="@+id/nav_contact_us"
        android:name="com.sohamerp.marsremedies.fragment.ContactUsFragment"
        android:label="@string/menu_contact_us"
        tools:layout="@layout/fragment_terms_condition" />

</navigation>

What I want to do:

Now I want to pass some values as bundle (arguments) in Fragment when its called.

Scenario: I have two fragment PrivacyPolicyFragment and TermsConditionsFragment, In both fragments, I am just opening link inside WebView accordingly. So When I click on menu item of Privacy Policy, I will pass link related to same.

In this new structure navigation/mobile_navigation.xml opening fragments, How can I pass arguments?

Any help?


回答1:


So I forgot to go through this link : Define Destination Arguments

But this answer helpful to all lazy peoples like me:

Add dependency in project level build.gradle:

classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.1.0"

Apply plugin in app level build.gradle:

apply plugin: "androidx.navigation.safeargs"

Using XML: predefined (static) value:

In xml file of navigation /navigation/mobile_navigation.xml declare argument tag as below or you can design through this link:

<fragment
    android:id="@+id/nav_privacy_policy"
    android:name="com.sohamerp.marsremedies.fragment.PrivacyPolicyFragment"
    android:label="@string/menu_privacy_policy"
    tools:layout="@layout/fragment_privacy_policy" >
    <argument
        android:name="privacyPolicyLink"
        app:argType="string"
        android:defaultValue="http://sohamerp.com/avo/avo_privacy_policy.html"/>
</fragment>

<fragment
    android:id="@+id/nav_terms"
    android:name="com.sohamerp.marsremedies.fragment.PrivacyPolicyFragment"
    android:label="@string/menu_terms"
    tools:layout="@layout/fragment_terms_condition" >
    <argument
        android:name="privacyPolicyLink"
        app:argType="string"
        android:defaultValue="http://sohamerp.com/avo/avo_privacy_policy.html"/>
</fragment>

Now you have to write code in your Fragment like:

if(getArguments() != null) {
    // The getPrivacyPolicyLink() method will be created automatically.
    String url = PrivacyPolicyFragmentArgs.fromBundle(getArguments()).getPrivacyPolicyLink();
}

Hope it will helps you others.




回答2:


To pass arguments to other Fragments/Destinations, use Safe Args which ensures type safety. Just like @bromden illustrated, Safe Args will generate a class for each fragment/destination where an action originates. You can then pass the arguments into the action that navigates to the Fragments.

In the receiving fragment, say PrivacyFragment if your code is in Kotlin, use by navArgs() property delegate to access the arguments. i.e.

val args: PrivacyFragmentArgs by navArgs()

To better understand this, visit Pass data between destinations




回答3:


You could implement NavigationView.OnNavigationItemSelectedListener And do something like this:

 override fun onNavigationItemSelected(item: MenuItem): Boolean {
   drawer_layout.closeDrawers()

        if (item.itemId == nv_navigation_drawer_navigation_view.checkedItem?.itemId)
            return false

     Handler().postDelayed({
                when (item.itemId) {
                    R.id.nav_privacy_policy -> {
                           val action = FragmentDirections.actionFragmentToPrivacyFragment("Policy link")

                     findNavController().navigate(action)

                    }
                }
            }, DRAWER_NAVIGATION_DELAY)
  return true
    }

And in xml you can add argument to the recieving fragment, in this case

   <fragment
    android:id="@+id/nav_privacy_policy"
    android:name=".fragment.PrivacyPolicyFragment"
    android:label="@string/menu_privacy_policy"
    tools:layout="@layout/fragment_privacy_policy">

    <argument
        android:name="policy"
        app:argType="string" />
</fragment>



回答4:


You can also pass serializable objects, enum values and arrays of primitive types. For example:

enum class ObjectType : Serializable {
    FIRST, SECOND
}

Then, add arguments to the xml

<fragment
        android:id="@+id/nav_profile"
        android:name="com.sohamerp.marsremedies.fragment.ProfileFragment"
        android:label="@string/menu_my_profile"
        tools:layout="@layout/fragment_profile" >

        <argument
            android:name="myObjectType"
            android:defaultValue="SECOND"
            app:argType="com.project.app.data.ObjectType" />
</fragment>

Note, that you should specify complete path!



来源:https://stackoverflow.com/questions/59452243/android-navigation-component-pass-value-arguments-in-fragments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!