我正在使用Android Jetpack中新的Navigation组件。
根活动设置非常简单:
Ascending
在导航图中定义Fragment的标题时效果很好。但对于一个片段,我想动态设置标题。
我尝试使用 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"
对我的魔力。有没有办法动态更新动作栏标题?
答案 0 :(得分:18)
从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
的{{1}}属性用大括号({{1}中的<fragment>
)包装了一个参数名称。然后,应用栏的标题将设置为该值标签的{title}
替换为"Title: {title}"
参数的值。
如果您需要比这更复杂的内容(例如,您想通过ID查找模型并从中读取属性),则需要使用更多手动方法,例如该问题的其他答案中概述的方法
答案 1 :(得分:6)
截至目前,Jetpack导航架构组件并未提供任何“内置”方式来执行此操作,您必须实现自己的“自定义”方法。
现有功能请求可以为添加到新Jetpack导航架构组件的目标上的动态标签获取功能。如果您在这里是因为您需要/需要此功能,请在此处标明现有功能请求: https://issuetracker.google.com/issues/80267266
答案 2 :(得分:6)
可以通过将活动强制转换为AppCompatActivity
来更改片段中的标题。
科特林
(requireActivity() as AppCompatActivity).supportActionBar?.title = "Hello"
Java
((AppCompatActivity) requireActivity()).getSupportActionBar().setTitle("Hello");
答案 3 :(得分:5)
考虑到您的主机活动是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
}
答案 4 :(得分:3)
另一种解决方案是使用ViewModel和LiveData,将viewmodel附加到您的活动和片段,在viewmodel中添加一个livingata字段
val title = MutableLiveData<String>()
从您的活动中观察此字段,如果已更改,请更新工具栏标题
viewModel?.title?.observe(this, Observer {
my_toolbar.title=it
})
从您想要的片段中更改viewmodel
中的标题字段viewModel?.title?.value="New title"
答案 5 :(得分:3)
从graph.xml文件中删除标签
android:label="fragment_info"
如果要从片段本身动态设置片段的标题,请使用老式的方法
getActivity().setTitle("Your Title");
答案 6 :(得分:2)
如果您在Activity中的setSupportActionBar上使用工具栏,并且希望以碎片形式更改其标题,则下面的代码可能会帮助您;)
(requireActivity() as MainActivity).toolbar.title = "Title here"
答案 7 :(得分:1)
在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")
答案 8 :(得分:1)
如果您的标题是从连接字符串中接收的,例如:
ActionBar actionBar = ((AppCompatActivity)
requireActivity()).getSupportActionBar();
if(actionBar!=null)
actionBar.setTitle(count + "items");
答案 9 :(得分: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>
答案 10 :(得分:0)
现在,导航UI支持此功能。现在,操作栏标题会动态更改。您只需要使用nav Controller设置操作栏即可。
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()
}
答案 11 :(得分:0)
您可以删除导航图中的 android:label ,然后在 onCreateView()
中编写activity?.title="your title"
答案 12 :(得分:0)
根据以下解决方案,无需手动访问工具栏。
如果您要将模型传递到目标片段中。 那么你就可以如下操作。
覆盖模型类中的 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>
我希望这会有所帮助。
答案 13 :(得分:-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"
}
}
}