如何从 SafeArgs 中的资源获取默认字符串值?

How to get a default string value from resources in SafeArgs?

我正在学习 Android NavigationUI,并尝试使用 Safe Args 中的字符串默认值设置工具栏标题。但是有一些问题。

'String resources' 文件:

    <string name="title_add_item">Add new items</string>

导航图文件。将标签设置为 Title: {title} 参数。

<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/nav_graph"
app:startDestination="@id/mainFragment">

<fragment
    android:id="@+id/addNewItemFragment"
    android:name="com.myapplication.AddNewItemFragment"
    android:label="Title: {title}"
    tools:layout="@layout/fragment_add_new_item" >
    <argument
        android:name="title"
        app:argType="string"
        android:defaultValue="@string/title_add_item" />
</fragment>
<fragment
    android:id="@+id/mainFragment"
    android:name="com.myapplication.MainFragment"
    android:label="fragment_main"
    tools:layout="@layout/fragment_main" >
    <action
        android:id="@+id/action_to_add_items_fragment"
        app:destination="@id/addNewItemFragment" />
</fragment>

如果{app:argType="string"}我得到一个错误:

 Caused by: org.xmlpull.v1.XmlPullParserException: unsupported value 'Add new items' for string. You must use a "reference" type to reference other resources.

如果 {app:argType="reference"} 应用程序运行正常,但我在标题中有一个数字(我认为这是一个资源 ID):

当然,我可以通过从参数中获取来在代码中分配工具栏标题的值。但是是否可以更改此代码以便正确填写标题?

看看over here.

您不需要使用参数来设置静态标题。 您可以使用 android:label.

将要在工具栏中显示的标题设置为导航图中的片段
<fragment
    android:id="@+id/addNewItemFragment"
    android:name="com.myapplication.AddNewItemFragment"
    android:label="@string/title_add_item"
    tools:layout="@layout/fragment_add_new_item" >

然后使用 setupWithNavController

设置工具栏
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(navController.graph)
findViewById<Toolbar>(R.id.toolbar)
    .setupWithNavController(navController, appBarConfiguration)

这样您就不需要覆盖 onSupportNavigateUp,一旦您导航到另一个片段,标题就会自动更新。

如果出于某种原因你真的想将参数与 android:label 中的值结合起来,那么除了使用 app:argType="reference" 并在你的代码中结合两者之外别无他法。

References to resources are supported only in reference types. Using a resource reference in any other type results in an exception.

随时为现有问题加注星标:https://issuetracker.google.com/issues/167959935。目前,您可以使用 app:argType="string" 对字符串值进行硬编码,或者尝试以编程方式设置直到它得到解决。

您可以将其作为引用类型并设置它并得到 reference/resource 和 getString(args.title)

nav_graph.xml

<fragment
    android:id="@+id/choose_scanner"
    android:name="com.myapp.ChooseScannerFragment"
    tools:layout="@layout/fragment_choose_scanner">
    <action
        android:id="@+id/action_scan_with_camera"
        app:destination="@+id/qr_scanner" />
</fragment>

<fragment
    android:id="@+id/qr_scanner"
    android:name="com.myapp.ScanFragment"
    tools:layout="@layout/fragment_scan">
    <argument
        android:name="show_back_button"
        android:defaultValue="false"
        app:argType="boolean" />

    <argument
        android:name="title"
        android:defaultValue="@string/connect_printer_device"
        app:argType="reference" />

    <argument
        android:name="message"
        android:defaultValue="@string/scan_printer_message"
        app:argType="reference" />
</fragment>

选择扫描仪片段

 findNavController().navigate(ChooseScannerFragmentDirections.actionScanWithCamera(
                    showBackButton = true,
                    title = R.string.step_1_scan_reference,
                    message = R.string.scan_reference_message
                ))

ScanFragment.kt

binding.message.text = getString(args.message)
        binding.title.text = getString(args.title)
        binding.back.visibility = if (args.showBackButton) View.VISIBLE else View.INVISIBLE