如何使用导航架构组件在应用栏中设置标题 [英] How to set title in app bar with Navigation Architecture Component
问题描述
我正在尝试使用导航架构组件,现在在设置标题时遇到了困难.如何以编程方式设置标题以及其工作方式?
I was trying out Navigation architecture component and is now having difficulties in setting the title. How do I set the title programmatically and also how it works?
为澄清我的问题,让我们举一个例子,其中,我用托管导航主机控制器的MainActivity
设置了一个简单的应用程序,MainFragment
有一个按钮,单击该按钮便转到
To clear my question, let's have an example, where, I've set up a simple app with MainActivity
hosting the navigation host controller, the MainFragment
has a button and on clicking the button it goes to DetailFragment
.
另一个问题 MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Setting up a back button
NavController navController = Navigation.findNavController(this, R.id.nav_host);
NavigationUI.setupActionBarWithNavController(this, navController);
}
@Override
public boolean onSupportNavigateUp() {
return Navigation.findNavController(this, R.id.nav_host).navigateUp();
}
}
MainFragment
public class MainFragment extends Fragment {
public MainFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button buttonOne = view.findViewById(R.id.button_one);
buttonOne.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.detailFragment));
}
}
DetailFragment
public class DetailFragment extends Fragment {
public DetailFragment() {
// Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_detail, container, false);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top"
android:layout_marginTop="?android:attr/actionBarSize"
app:defaultNavHost="true"
app:layout_anchor="@id/bottom_appbar"
app:layout_anchorGravity="top"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:navGraph="@navigation/mobile_navigation" />
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottom_appbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:layout_gravity="bottom" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@id/bottom_appbar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
navigation.xml
<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.example.MainFragment"
android:label="fragment_main"
tools:layout="@layout/fragment_main" >
<action
android:id="@+id/toAccountFragment"
app:destination="@id/detailFragment" />
</fragment>
<fragment
android:id="@+id/detailFragment"
android:name="com.example.DetailFragment"
android:label="fragment_account"
tools:layout="@layout/fragment_detail" />
</navigation>
因此,在启动我的应用时,标题为"MainActivity" .像往常一样,它显示MainFragment
,其中包含要转到DetailFragment
的按钮.在DialogFragment
中,我将标题设置为:
So when start my app, the title is "MainActivity". As usual it shows the MainFragment
that contains the button to go to DetailFragment
. In the DialogFragment
I've set the title as:
getActivity().getSupportActionBar().setTitle("Detail");
第一个问题:因此,单击MainFragment
上的按钮转到DetailFragment
,它确实到达了那里,标题更改为详细信息".但是,单击后退按钮后,标题将更改为"fragment_main" .所以我将这行代码添加到MainFragment
:
First Problem: So clicking the button on the MainFragment
to goto DetailFragment
, it does go there and the title changes to "Detail". But on clicking the back button, the title changes to "fragment_main". So I added this line of code to MainFragment
:
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// ...
//Showing the title
Navigation.findNavController(view)
.getCurrentDestination().setLabel("Hello");
}
现在,从DetailFragment
返回到MainFragment
的标题更改为"Hello".但是出现了第二个问题,当我关闭应用程序并重新启动时,标题会变回"MainActivity",尽管它应该显示"Hello",知道吗?
Now the while returning back from DetailFragment
to MainFragment
the title changes to "Hello". But here comes the second problem, when I close the app and start again, the title changes back to "MainActivity" though it should be showing "Hello" instead, know?
好,然后在MainFrgment
中添加setTitle("Hello")
也不起作用.例如,活动开始,标题为"Hello",转到DetailsFragment
并再次按返回按钮,标题回到"fragment_main".
Ok, then adding setTitle("Hello")
in MainFrgment
is not working too. For example, the activity starts and the title is "Hello", go to DetailsFragment
and press the back button again, the title goes back to "fragment_main".
唯一的解决方案是在MainFragment
中同时包含setTitle("Hello")
和Navigation.findNavController(view).getCurrentDestination().setLabel("Hello")
.
The only solution is to have both setTitle("Hello")
along with Navigation.findNavController(view).getCurrentDestination().setLabel("Hello")
in MainFragment
.
那么使用导航组件显示片段标题的正确方法是什么?
So what is the proper way to show the title for fragments using Navigation Component?
推荐答案
由于其他人仍在参与回答此问题,所以我要回答我自己的问题,因为自那时以来API发生了变化.
As others are still participating in answering this question, let me answer my own question as APIs has changed since then.
首先,从navigation.xml
(又名导航图)中,从要更改标题的片段中删除android:label
.
First, remove android:label
from the fragment/s that you wish to change the title of, from within navigation.xml
(aka Navigation Graph),.
现在,您可以通过调用
(requireActivity() as MainActivity).title = "My title"
但是您应该使用的首选方式是API MainActivity中的"noreferrer> NavController.addOnDestinationChangedListener
.一个例子:
But the preferred way you should be using is the API NavController.addOnDestinationChangedListener
from within MainActivity
. An Example:
NavController.OnDestinationChangedListener { controller, destination, arguments ->
// compare destination id
title = when (destination.id) {
R.id.someFragment -> "My title"
else -> "Default title"
}
// if (destination == R.id.someFragment) {
// title = "My title"
// } else {
// title = "Default Title"
// }
}
这篇关于如何使用导航架构组件在应用栏中设置标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!