Установить заголовок панели инструментов динамически с помощью навигационного компонента

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

Предположим, у меня есть список элементов, каждый элемент, по которому я щелкнул, это новый открытый фрагмент, поэтому я пытаюсь динамически изменять заголовок панели инструментов для каждого элемента.

Я старался:

it.findNavController().navigate(direction)
it.findNavController().currentDestination!!.label = someTitle

Но это не работает.

Есть несколько смежных тем, а именно:

Как установить заголовок на панели приложения с помощью компонента Navigation Architecture

Но это не решает мою проблему эффективно, это обходной путь.

1 ответ

Решение

Навигация поддерживает аргументы в метках начиная с версии 1.0.0-alpha08 или выше:

Метки назначения при использовании с методами NavigationUI теперь будут автоматически заменяться {argName} случаи в вашем android:label с правильным аргументом b/80267266

Поэтому вы можете установить ярлык на android:label="{dynamicTitle}", а затем передать аргумент вашему navigate вызов. Поскольку вы используете Safe Args, вы хотите добавить аргумент к месту назначения:

<fragment
    android:id="@+id/myFragment"
    android:name=".MyFragment"
    android:label="{dynamicTitle}">
  <argument
      android:name="dynamicTitle"
      app:argType="string"/>
</fragment>

Затем передайте свой динамический заголовок при построении ваших направлений:

val directions = YourDirections.actionToMyFragment(someTitle)
it.findNavController().navigate(directions)

Конечно, вы можете прослушивать навигационные события самостоятельно и использовать свои собственные OnDestinationChangedListener делать все, что вы хотите, включая установку метки на то, что вы хотите. Нет необходимости использовать NavigationUI, и любой слушатель, добавляемый после вызова методов NavigationUI, будет переопределять все, что он устанавливает.

Если вы передаете обычай Object в качестве параметра вы можете использовать navController.addOnDestinationChangedListener.

navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
    @Override
    public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
        Log.i(TAG, "onDestinationChanged");
        switch (destination.getId()) {
            case R.id.mainFragment:
                updateToolbarAndBottomNavigation("Main Title", "Main Subtitle", View.VISIBLE);
                break;
            case R.id.shopFragment:
                updateToolbarAndBottomNavigation("custom title", null, View.VISIBLE);
                break;
            case R.id.shopcartFragment:
                StoreEntity store = (StoreEntity) arguments.get("storeEntity");
                Log.i(TAG, "onDestinationChanged: ShopCartFragment args: "+store.getName());
                updateToolbarAndBottomNavigation(store.getName(), null, View.GONE);
                break;
        }

    }
});

private void updateToolbarAndBottomNavigation(String title, String subtitle, int visibility) {
    getSupportActionBar().setTitle(title);
    getSupportActionBar().setSubtitle(subtitle);
    bottomNavigationView.setVisibility(visibility);
}

Где arguments.get() был получен из android:name в nav_graph.xml.

<fragment
        android:id="@+id/shopcartFragment"
        android:name="com.myapp.ShopcartFragment"
        tools:layout="@layout/fragment_shopcart" >
        <argument
            android:name="storeEntity" // GET ARGUMENTS NAME HERE
            app:argType="com.myapp.LocalDatabase.StoreEntity" />
    </fragment>

Надеюсь, это поможет большему количеству людей!

Вы можете добавить метод обновления заголовка фрагмента и вызвать его в методе фрагмента onStart()

fun updateToolbarTitle(title: String) {
    supportActionBar?.title = title
}

и удалите атрибут lable из тега в вашем nav_graph.xml, чтобы он был таким

<fragment
    android:id="@+id/myFragment"
    android:name=".MyFragment"/>
Другие вопросы по тегам