使用 AndroidX 导航的片段中的动态操作栏标题



我正在使用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,只需将以下代码添加到你的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
}

如果您在活动中使用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"

相关内容

  • 没有找到相关文章

最新更新