web-dev-qa-db-ja.com

AndroidXナビゲーションを使用したフラグメントからの動的ActionBarタイトル

新しい Navigation from Android Jetpack。

ルートアクティビティのセットアップは非常に簡単です。

_override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(toolbar)

    val navController = findNavController(R.id.navigationFragment)
    setupActionBarWithNavController(navController)

    bottomNavigationView.setupWithNavController(navController)
}
_

ナビゲーショングラフでフラグメントのタイトルが定義されている場合、うまく機能します。しかし、1つのフラグメントについて、タイトルを動的に設定したいと思います。

findNavController().currentDestination.label = "Hello world"で試しましたが、何もしません。

もちろん_(activity as? AppCompatActivity)?.supportActionBar?.title = "Hello world"_のようなトリックを使用することもできますが、setupActionBarWithNavController()が私のために行う魔法を壊すと感じています。アクションバーのタイトルを動的に更新する方法はありますか?

23
Jonas

1.0.0-alpha08、ナビゲーションビットがナビゲーションアクションの引数である場合、NavigationUIビットでタイトルを動的に設定できます。

そのため、たとえば、ナビゲーショングラフには次のようなものがあります。

  <fragment
    Android:id="@+id/displayFragment"
    Android:name="com.commonsware.jetpack.sampler.nav.DisplayFragment"
    Android:label="Title: {title}" >
    <argument
      Android:name="modelId"
      app:argType="string" />
    <argument
      Android:name="title"
      app:argType="string" />
  </fragment>

ここでは、Android:label属性の<fragment>には引数名が中括弧({title} in "Title: {title}"。アプリバーのタイトルは、ラベルの値に設定され、{title}は、title引数の値に置き換えられます。

それよりも複雑なものが必要な場合(たとえば、IDでモデルを検索し、そこからプロパティを読み取る場合)、この質問に対する他の回答で概説されているような、より多くの手動アプローチを使用する必要があります。

38
CommonsWare

現在のところ、Jetpack Navigation Architectureコンポーネントは、これを行うための「組み込み」方法を提供していません。そのためには、独自の「カスタム」メソッドを実装する必要があります。

新しいJetpack Navigation Architectureコンポーネントに追加された宛先の動的ラベルの機能を取得するための既存の機能要求があります。この機能が必要/必要なためにここにいる場合は、既存の機能リクエストにスターを付けてください: https://issuetracker.google.com/issues/80267266

6
Bradleycorn

ホストアクティビティがMainActivityであることを考慮して、次のコードをMainActivityonCreate funに追加するだけです。

val navController = Navigation.findNavController(this, R.id.nav_Host_fragment)

// setting title according to fragment
navController.addOnDestinationChangedListener { 
    controller, destination, arguments ->
        toolbar.title = navController.currentDestination?.label
}
5

さて、ナビゲーションUIはこの機能をサポートしています。これで、ActionBarタイトルが動的に変更されます。 ActionBarNavControllerをセットアップする必要があります。

private lateinit var appBarConfiguration: AppBarConfiguration

private lateinit var navController: NavController

override fun onCreate(savedInstanceState: Bundle?) {
    preferedTheme()
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(toolbar)
    navController = findNavController(R.id.nav_controller_fragment)
    appBarConfiguration = AppBarConfiguration(navController.graph)
    setupActionBarWithNavController(navController, appBarConfiguration)
}

そして、ナビゲーショングラフにアクションバーのラベルを設定します:

<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/mainFragment">

<fragment Android:id="@+id/mainFragment"
          Android:name="com.cinderellaman.general.ui.fragments.MainFragment"
          Android:label="General"
          tools:layout="@layout/main_fragment"/>

そして現在、Navigate Upもサポートしています。

override fun onSupportNavigateUp(): Boolean {
    return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
3
Hussnain Haidar

graph.xmlファイルからラベルを削除

Android:label="fragment_info"

フラグメント自体からフラグメントのタイトルを動的に設定する場合は、オールドスクールのアプローチを使用します

getActivity().setTitle("Your Title");
3
Naveen Rao

別の解決策は、ViewModelとLiveDataを使用して、viewmodelをアクティビティとフラグメントに接続し、viewmodel内にlivedataフィールドを追加することです。

val title = MutableLiveData<String>()

アクティビティからこのフィールドを観察し、変更されている場合はツールバーのタイトルを更新します

viewModel?.title?.observe(this, Observer { 
        my_toolbar.title=it
    })

目的のフラグメントから、ビューモデル内のタイトルフィールドを変更します

viewModel?.title?.value="New title"
3
Alex

issue が修正されるまで、単純なリスナーが動作します:

/**
 * Temporary solution to dynamically change title of actionbar controlled by Navigation component
 * Should be removed as soon as the bug on Navigation will be fixed: (https://issuetracker.google.com/issues/80267266)
 */
interface TempToolbarTitleListener {
    fun updateTitle(title: String)
}

class MainActivity : AppCompatActivity(), TempToolbarTitleListener {

    ...

    override fun updateTitle(title: String) {
        binding.toolbar.title = title
    }
}

フラグメントからタイトルを変更:

(activity as TempToolbarTitleListener).updateTitle("custom title")
1
Francis

アクティビティのタイトルを試すと、フラグメントのタイトルがオーバーライドされるようです。安全のため、onResumeを付ける必要があります。

override fun onResume() {
    super.onResume()
    activity?.toolbar.title = "YOUR_TITLE_HERE"
}

わたしにはできる !

注:アクティビティにツールバーウィジェットが必要です

アクティビティのxmlにこのようなツールバーを追加します

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/container"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"">

    <com.google.Android.material.appbar.AppBarLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content" />

    </com.google.Android.material.appbar.AppBarLayout>

    <!-- Other Widgets -->

</androidx.coordinatorlayout.widget.CoordinatorLayout>
0
Dilroop Singh