Как получить значение строки по умолчанию из ресурсов в SafeArgs?

Я только изучаю Android NavigationUI и пытаюсь установить заголовок панели инструментов, используя строковое значение по умолчанию из Safe Args. Но есть некоторые проблемы по этому поводу.

Файл "Строковые ресурсы":

    <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"} приложение работает, но у меня есть номер в заголовке (я думаю, что это идентификатор ресурса):

Конечно, я могу присвоить значение заголовку панели инструментов в коде, получив его из аргументов. Но можно ли изменить этот код так, чтобы заголовок был заполнен правильно?

3 ответа

Ссылки на ресурсы поддерживаются только в ссылочных типах. Использование ссылки на ресурс в любом другом типе приводит к исключению.

Не стесняйтесь отмечать существующую проблему: https://issuetracker.google.com/issues/167959935. На данный момент u может жестко закодировать строковое значение с помощью app:argType="string" или попробуйте настроить программно, пока он не будет решен.

Взгляните сюда.

Вам не нужно использовать аргументы для установки статического заголовка. Вы можете просто установить заголовок, который должен отображаться на панели инструментов, для фрагмента в навигационном графике с помощью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" и объединяя их в вашем коде.

Вы можете просто сделать его ссылочным типом, установить его и получить как ссылку/ресурс с помощью 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
Другие вопросы по тегам