74

我正在使用来自 Android Jetpack的新导航组件。

根 Activity 设置非常简单:

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

当在导航图中定义片段的标题时,它工作得很好。但是对于一个片段,我想动态设置标题。

我试过了,findNavController().currentDestination.label = "Hello world"但它什么也没做。

我当然可以使用类似的技巧(activity as? AppCompatActivity)?.supportActionBar?.title = "Hello world",但我觉得它会打破对我有用的魔法setupActionBarWithNavController()。有什么方法可以动态更新操作栏标题吗?

4

15 回答 15

138

从 开始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 查找模型并从中读取一个属性——你将需要使用更多的手动方法,例如在这个问题的其他答案中概述的那些。

于 2019-02-03T15:21:03.980 回答
33

可以通过将活动转换为 来更改片段中的标题AppCompatActivity

科特林

(requireActivity() as AppCompatActivity).supportActionBar?.title = "Hello"

爪哇

((AppCompatActivity) requireActivity()).getSupportActionBar().setTitle("Hello");
于 2020-03-09T09:11:35.867 回答
18

考虑到您的主机活动是MainActivity,只需将以下代码添加到您MainActivityonCreate乐趣

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
}
于 2018-12-13T06:44:41.030 回答
11

如果您在 Activity 中使用 setSupportActionBar 上的工具栏,并且您想在片段中更改其标题,那么下面的代码可能会对您有所帮助;)

(requireActivity() as MainActivity).toolbar.title = "Title here"
于 2019-10-18T08:42:18.583 回答
9

到目前为止,Jetpack 导航架构组件不提供任何“内置”方法来执行此操作,您必须实现自己的“自定义”方法来执行此操作。

有一个现有的功能请求来获取添加到新 Jetpack 导航架构组件的目的地动态标签的功能。如果您因为想要/需要此功能而来到这里,请在此处为现有功能请求加注星标: https ://issuetracker.google.com/issues/80267266

于 2018-06-18T16:14:15.950 回答
8

从 graph.xml 文件中删除标签

android:label="fragment_info"

如果您想从片段本身动态设置片段的标题,请使用老派方法

getActivity().setTitle("Your Title");
于 2018-12-18T09:57:18.290 回答
5

好吧,现在导航 UI 支持此功能。现在ActionBar标题动态变化。您只需要ActionBar使用NavController.

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

现在它还支持向上导航:

override fun onSupportNavigateUp(): Boolean {
    return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
于 2019-02-04T03:42:21.680 回答
3

另一种解决方案是使用 ViewModel 和 LiveData,将 viewmodel 附加到您的活动和片段,在 viewmodel 内添加一个 livedata 字段

val title = MutableLiveData<String>()

从您的活动中观察此字段,如果更改,则更新工具栏标题

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

从您想要的片段中更改视图模型中的标题字段

viewModel?.title?.value="New title"
于 2018-06-07T06:35:28.917 回答
2

问题得到解决之前,简单的听众正在为我工​​作:

/**
 * 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")
于 2018-07-12T13:16:17.750 回答
1

如果您的标题是从连接的字符串中收到的,例如:

ActionBar actionBar = ((AppCompatActivity) 
  requireActivity()).getSupportActionBar();
  
if(actionBar!=null)                   
   actionBar.setTitle(count + "items"); 
于 2021-01-25T12:33:54.757 回答
1

基于@kaustubh-trivedi 的回答,如果您使用的是 MVVM(如 Android Studio FirstFragment/SecondFragment 示例):

KOTLIN 版本

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
}

JAVA版

        navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
                binding.toolbar.setTitle(destination.getLabel());
            }
        });
于 2021-09-26T21:49:32.333 回答
1

根据以下解决方案,无需手动访问工具栏。

如果您要将模型传递到目的地片段。然后你可以做如下。

toString()模型类中的覆盖方法

data class UserModel(
    val userId: String = ""
    val firstName: String = "",
    val lastName: String = ""  
) {

    override fun toString(): String {
        return "$firstName $lastName"
    }
}

现在,在nav_grap.xml 文件中,执行以下操作。android:label="{UserData}"将从模型类的 toString() 方法中获取标签。

<fragment
    android:id="@+id/messagesFragment"
    android:name="com.app.mydemoapp.ui.messages.MessagesFragment"
    android:label="{UserData}"
    tools:layout="@layout/fragment_messages">

    <argument
        android:name="UserData"
        app:argType="com.app.mydemoapp.model.UserModel" />

</fragment>

我希望,这会有所帮助。

于 2021-07-20T05:41:04.277 回答
1

您可以在活动中添加 addOnNavigatedListener,并根据当前目的地更改标题

 findNavController(nav_host_fragment).addOnNavigatedListener { controller, destination ->
        when(destination.id) {
            R.id.destination1 -> {
                my_toolbar.title= "Some title"
            }
            R.id.destination2 -> {
                my_toolbar.title= "Othertitle"

            }

    }
}
于 2018-05-30T13:36:24.290 回答
0

在尝试活动的标题时,它似乎覆盖了片段的标题。为了安全起见,您必须穿上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>
于 2019-01-16T22:01:45.953 回答
-2

您可以在导航图中删除android:label然后写入onCreateView()

activity?.title="your title"
于 2019-10-03T18:20:52.960 回答