我正在使用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)
}
当片段的标题在导航图中定义时,它运行良好。但是对于一个片段,我想动态设置标题。
我尝试了findNavController().currentDestination.label = "Hello world"
但它什么也没做。
我当然可以使用像(activity as? AppCompatActivity)?.supportActionBar?.title = "Hello world"
这样的技巧,但我觉得它会打破setupActionBarWithNavController()
为我做的魔法。有什么方法可以动态更新操作栏标题吗?
截至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>
在这里,我们<fragment>
的android:label
属性有一个用大括号括起来的参数名称({title}
在"Title: {title}"
中。然后,应用栏的标题将设置为标签的值,{title}
替换为title
参数的值。
如果您需要比这更复杂的东西(例如,您希望按 ID 查找模型并从中读取属性),您将需要使用更多的手动方法,例如此问题的其他答案中概述的方法。
可以通过将活动转换为AppCompatActivity
来更改片段中的标题。
科特林
(requireActivity() as AppCompatActivity).supportActionBar?.title = "Hello"
爪哇岛
((AppCompatActivity) requireActivity()).getSupportActionBar().setTitle("Hello");
考虑到你的主机活动是MainActivity
,只需将以下代码添加到你的MainActivity
onCreate
乐趣
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
}
如果您在活动中使用setSupportActionBar上的工具栏,并且想在片段中更改其标题,那么下面的代码可能会帮助您;)
(requireActivity() as MainActivity).toolbar.title = "Title here"
截至目前,Jetpack 导航体系结构组件不提供任何"内置"方法来执行此操作,您必须实现自己的"自定义"方法来执行此操作。
有一个现有的功能请求,用于获取添加到新 Jetpack 导航体系结构组件的目的地上的动态标签的功能。如果您在这里是因为您想要/需要此功能,请在此处为现有功能请求加星标: https://issuetracker.google.com/issues/80267266
从图形.xml文件中删除标签
android:label="fragment_info"
如果要从片段本身动态设置片段的标题,请使用老式方法
getActivity().setTitle("Your Title");
<</div> div class="one_answers">另一种解决方案是使用ViewModel和LiveData,将视图模型附加到您的活动和片段,在viewmodel中添加一个实时数据字段
val title = MutableLiveData<String>()
在您的活动中观察此字段,如果更改,请更新工具栏标题
viewModel?.title?.observe(this, Observer {
my_toolbar.title=it
})
从所需的片段中更改视图模型内的标题字段
viewModel?.title?.value="New title"
好吧,现在导航 UI 支持此功能。现在,ActionBar
标题会动态更改。您只需要使用NavController
设置ActionBar
即可。
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()
}
在问题得到解决之前,简单的侦听器正在为我工作:
/**
* 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")
基于@kaustubh-trivedi答案,如果您使用的是MVVM(如Android Studio FirstFragment/SecondFragment示例):
科特林版本
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
}
爪哇版本
navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
@Override
public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
binding.toolbar.setTitle(destination.getLabel());
}
});
您可以在活动中添加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"
}
}
}
如果您的标题是从串联字符串接收的,例如:
ActionBar actionBar = ((AppCompatActivity)
requireActivity()).getSupportActionBar();
if(actionBar!=null)
actionBar.setTitle(count + "items");
根据以下解决方案,无需手动访问工具栏。
如果要将模型传递到目标片段中。 然后你可以做如下。
重写模型类中的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>
我希望这会有所帮助。
在尝试活动的标题时,它似乎覆盖了片段的标题。为了安全起见,您必须穿上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>
只需在片段中使用此代码.java如果您使用的是导航组件,并且想在 JAVA 中以编程方式更改片段的标签
Navigation.findNavController(view).addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
@Override
public void onDestinationChanged(@NonNull NavController navController, @NonNull NavDestination navDestination, @Nullable Bundle bundle) {
navController.findDestination(R.id.YOUR_FRAGMENT_ID_HERE).setLabel(YOUR_LABEL_HERE);
}
});
你可以在导航图中删除android:label,然后在onCreateView()中写入
activity?.title="your title"