簡體   English   中英

Android 導航組件:在片段中傳遞值(參數)

[英]Android Navigation Component : Pass value (arguments) in fragments

我做了什么:

我創建了Navigation Drawer Activity ,更新了Navigation Drawer Activity 的新格式,根據新的 Android 架構,我通過Navigation Component結構得到了它。

帶有NavControllerNavigationUINavigationView代碼在下面,當我單擊任何導航項時,它正在打開片段。

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

這是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" />

使用此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>

我想做的事:

現在我想在 Fragment 被調用時將一些值作為包(參數)傳遞。

場景:我有兩個片段PrivacyPolicyFragmentTermsConditionsFragment ,在這兩個片段中,我只是相應地打開 WebView 內的鏈接。 所以當我點擊Privacy Policy的菜單項時,我會傳遞一個與之相關的鏈接。

在這個新結構navigation/mobile_navigation.xml打開片段中,我怎樣才能通過 arguments?

有什么幫助嗎?

所以我忘了通過這個鏈接: 定義目的地參數

但是這個答案對像我這樣的所有懶惰的人都有幫助:

在項目級build.gradle 中添加依賴

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

在應用級build.gradle 中應用插件:

apply plugin: "androidx.navigation.safeargs"

使用 XML:預定義(靜態)值:

在導航/navigation/mobile_navigation.xml 的xml 文件中聲明argument標簽如下,或者您可以通過此鏈接進行設計:

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

現在您必須在 Fragment 中編寫代碼,例如:

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

希望它會幫助你其他人。

要將參數傳遞給其他片段/目標,請使用確保類型安全的安全參數 就像@bromden 所示,Safe Args 將為action起源的每個片段/目的地生成一個類。 然后,您可以傳遞參數到action導航到該片段。

在接收片段中,如果您的代碼在 Kotlin 中,請說PrivacyFragment ,通過navArgs()屬性委托來訪問參數。 IE

val args: PrivacyFragmentArgs by navArgs()

為了更好地理解這一點,請訪問目的地之間的通行證數據

您可以實現NavigationView.OnNavigationItemSelectedListener並執行以下操作:

 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
    }

在 xml 中,您可以向接收片段添加參數,在這種情況下

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

您還可以傳遞可序列化對象、枚舉值和基本類型數組。 例如:

enum class ObjectType : Serializable {
    FIRST, SECOND
}

然后,將參數添加到 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>

請注意,您應該指定完整路徑!

在這種情況下,您可以使用

  private NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
  // Create the Bundle to pass, you can put String, Integer, or serializable object
  Bundle bundle = new Bundle();
  bundle.putString("link","http://yourlink.com/policy");
  bundle.putSerializable("USER", user); // Serializable Object
  navController.navigate(R.id.nav_terms, bundle); // called fragment with agruments

如果有任何幫助,您可以回復它

使用 NavController NavGraph 導航從起始目的地傳遞數據非常簡單。 我使用它來顯示與訂單 header 關聯的訂單行:

    private void showRepositionLinesFragment(AppObjects.RepOrderHeader orderHeader) {

    int number = orderHeader.getOrderNumber();
    String orderNumber = String.format("%06d",number);
    String createDate = orderHeader.getCreateDate();
    Globals.LogTrace(this, AppAlertDialog.DialogType.Info,
        "Navigate to FragRepoLines with orderNumber: " + orderNumber,false);
    NavController navController = NavHostFragment.findNavController(FragmentRepositionHeaders.this);
    Bundle bundle = new Bundle();
    bundle.putString(getString(R.string.arg_header_ordernumber),orderNumber);
    bundle.putString(getString(R.string.arg_repheader_createdate), createDate);
    navController.getGraph().findNode(R.id.FragRepoLines).setLabel(orderNumber + " " + createDate);
    navController.navigate(R.id.action_FragRepoHeaders_to_FragRepoLines,bundle);
}

從處理訂單行的片段中獲取數據變得更加復雜。 使用 NavController getArguments() 嘗試了幾個小時。 最后,這對我有用。

在開始片段中:

    NavController navController = NavHostFragment.findNavController(this);
    // We use a String here, but any type that can be put in a Bundle is supported
    MutableLiveData<String> liveData = navController.getCurrentBackStackEntry()
        .getSavedStateHandle()
        .getLiveData(getString(R.string.arg_header_ordernumber));
    liveData.observe(getViewLifecycleOwner(), new Observer<String>() {
        @Override
        public void onChanged(String s) {
            Globals.LogTrace(this, AppAlertDialog.DialogType.Info, "+++++++++  liveData changed -> " + s, false);
        }
    });

在目標片段中:

    String arg = getString(R.string.arg_header_ordernumber);
    NavController navController = NavHostFragment.findNavController(this);
    NavBackStackEntry navBackStackEntry = navController.getCurrentBackStackEntry();
    if (navBackStackEntry != null) {
        SavedStateHandle savedStateHandle = navBackStackEntry.getSavedStateHandle();
        if (savedStateHandle != null) {
            savedStateHandle.set(arg, "000000");
        } else {
            Globals.LogTrace(this, AppAlertDialog.DialogType.Info,"savedStateHandle == null",false);
        }
    } else {
        Globals.LogTrace(this, AppAlertDialog.DialogType.Info,"navBackStackEntry == null",false);
    }

來源: 以編程方式與導航組件交互

我將 navController.getPreviousBackStackEntry() 更改為 navController.getCurrentBackStackEntry()

在較新版本的 Android Studio 3.2+ 中,需要在 build.gradle 文件中添加以下依賴項和插件

第1步

項目級build.gradle 中添加依賴

dependencies {
    classpath 'androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5'
}

App-Level build.gradle 中應用插件

plugins {
    id 'androidx.navigation.safeargs' 
}

第2步

  1. 在導航文件中, res/navigation/nav_graph.xml
  2. 使用動作標簽在任何片段或內部片段中聲明參數標簽
  3. 項目清單

示例 xml 代碼

 <fragment
     android:id="@+id/nav_register"
     android:name="com.pd.demo.ui.profile.RegisterFragment"
     android:label="@string/title_register"
     tools:layout="@layout/fragment_register">
     <action
         android:id="@+id/action_nav_register_to_nav_verify_otp"
         app:destination="@id/nav_verify_otp">
         <argument
             android:name="mobile"
             app:argType="string" />
         <argument
             android:name="password"
             app:argType="string" />
     </action>
 </fragment>

步驟 3

在 Kotlin 代碼下方,將參數傳遞給目標片段

val bundle = bundleOf("mobile" to binding.etMobileNo.text.toString().trim())
Navigation.findNavController(binding.root).navigate(R.id.action_nav_register_to_nav_verify_otp, bundle)

第四步

在 Kotlin 代碼下方,從源片段獲取包參數

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    mobileNo = arguments!!.getString("mobile").toString()
    password = arguments!!.getString("password").toString()
}

此代碼將有所幫助

簡單快速的解決方案:

在目的地之間傳遞參數

Bundle bundle = new Bundle();
bundle.putString("amount", amount);
Navigation.findNavController(view).navigate(R.id.confirmationAction, bundle);

和接收

TextView tv = view.findViewById(R.id.textViewAmount);
tv.setText(getArguments().getString("amount"));

我遇到了同樣的問題,但我仍然無法使用片段方向傳遞參數。 因為我需要在我的幾個片段中使用值,所以我決定在我的主要活動中使用一個伴隨對象。 它可能不是最好的,但它解決了問題: class MainActivity : AppCompatActivity() {

    companion object{
        var myGlobalVar = "Example"
    }

override fun onCreate(savedInstanceState: Bundle?) {.... 

然后我可以通過導入它來訪問它在我所有片段中的值:

import myAppPackage.MainActivity.Companion.myGlobalVar

我不得不從我的 navGraph 中刪除參數,但我仍然可以在后台訪問它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM