Raj*_*shi 10 android android-layout android-architecture-navigation androidx
我正在尝试导航架构组件,但现在在设置标题时遇到了困难。如何以编程方式设置标题以及其工作方式?
为了澄清我的问题,让我们举个例子,在这里,我建立了一个简单的应用程序,用于MainActivity托管导航主机控制器,该应用程序MainFragment有一个按钮,然后单击该按钮转到DetailFragment。
来自另一个问题的相同代码,该问题涉及堆栈溢出的多个应用栏。
主要活动
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();
}
}
Run Code Online (Sandbox Code Playgroud)
主片段
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));
}
}
Run Code Online (Sandbox Code Playgroud)
详细片段
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
因此,当启动我的应用程序时,标题为“ MainActivity”。与往常一样,它显示MainFragment包含要转到的按钮DetailFragment。在中,DialogFragment我将标题设置为:
getActivity().getSupportActionBar().setTitle("Detail");
Run Code Online (Sandbox Code Playgroud)
第一个问题:因此,单击MainFragmentgoto 上的按钮DetailFragment,它确实到达了那里,标题变为“ Detail”。但是,单击后退按钮后,标题将更改为“ fragment_main”。所以我将这行代码添加到MainFragment:
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// ...
//Showing the title
Navigation.findNavController(view)
.getCurrentDestination().setLabel("Hello");
}
Run Code Online (Sandbox Code Playgroud)
现在从在返回回DetailFragment给MainFragment标题更改为“你好”。但这是第二个问题,当我关闭应用程序并重新启动时,标题改回“ MainActivity”,尽管它应该显示“ Hello”,知道吗?
好吧,然后添加setTitle("Hello")在MainFrgment不工作了。例如,活动开始,标题为“ Hello”,转到DetailsFragment并再次按返回按钮,标题回到“ fragment_main”。
唯一的解决方案是同时setTitle("Hello")使用Navigation.findNavController(view).getCurrentDestination().setLabel("Hello")in和MainFragment。
那么,使用导航组件显示片段标题的正确方法是什么?
Ali*_*ran 15
如果您未指定应用栏(默认应用栏),则可以在片段中使用此代码
(activity as MainActivity).supportActionBar?.title = "Your Custom Title"
Run Code Online (Sandbox Code Playgroud)
记得删除android:label导航图中的属性
快乐码^-^
ʍѳђ*_*ઽ૯ท 12
实际上是因为:
android:label="fragment_main"
Run Code Online (Sandbox Code Playgroud)
您已在xml中设置的内容。
那么,
Fragment使用Navigation Component 显示s 标题的正确方法是什么?
setTitle()在这一点上工作。但是,由于您为这些设置了标签Fragment,因此在重新创建时可能会再次显示标签Activity。解决方案可能是删除android:label,然后使用代码来处理您的事情:
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("your title");
Run Code Online (Sandbox Code Playgroud)
要么:
((AppCompatActivity) getActivity()).getSupportActionBar().setSubtitle("your subtitle");
Run Code Online (Sandbox Code Playgroud)
在中onCreateView()。
找到了解决方法:
interface TempToolbarTitleListener {
fun updateTitle(title: String)
}
class MainActivity : AppCompatActivity(), TempToolbarTitleListener {
...
override fun updateTitle(title: String) {
binding.toolbar.title = title
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
(activity as TempToolbarTitleListener).updateTitle("custom title")
Run Code Online (Sandbox Code Playgroud)
也请检查以下内容:使用AndroidX导航的片段中的动态ActionBar标题
小智 12
根据经验,NavController.addOnDestinationChangedListener
似乎表现不错。我下面的 MainActivity 示例发挥了神奇的作用
navController.addOnDestinationChangedListener{ controller, destination, arguments ->
title = when (destination.id) {
R.id.navigation_home -> "My title"
R.id.navigation_task_start -> "My title2"
R.id.navigation_task_finish -> "My title3"
R.id.navigation_status -> "My title3"
R.id.navigation_settings -> "My title4"
else -> "Default title"
}
}
Run Code Online (Sandbox Code Playgroud)
fra*_*kee 12
现在使用 Kotlin 有一种更简单的方法来实现这一点,并且androidx.navigation:navigation-ui-ktx:
import androidx.navigation.ui.setupActionBarWithNavController
class MainActivity : AppCompatActivity() {
private val navController: NavController
get() = findNavController(R.id.nav_host_fragment)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this,R.layout.activity_main)
setSupportActionBar(binding.toolbar)
setupActionBarWithNavController(navController) // <- the most important line
}
// Required by the docs for setupActionBarWithNavController(...)
override fun onSupportNavigateUp() = navController.navigateUp()
}
Run Code Online (Sandbox Code Playgroud)
基本上就是这样。不要忘记android:label在导航图中指定。
由于其他人仍在参与回答此问题,因此自此之后API发生了变化,让我回答我自己的问题。
首先,android:label从内部navigation.xml(即导航图)中,从您想要更改标题的片段中删除。
现在您可以Fragment通过调用更改标题
(requireActivity() as MainActivity).title = "My title"
Run Code Online (Sandbox Code Playgroud)
但是,你应该使用的最佳方法是API NavController.addOnDestinationChangedListener从内部MainActivity。一个例子:
NavController.OnDestinationChangedListener { controller, destination, arguments ->
title = when (destination) {
R.id.someFragment -> "My title"
else -> "Default title"
}
// if (destination == R.id.someFragment) {
// title = "My title"
// } else {
// title = "Default Title"
// }
}
Run Code Online (Sandbox Code Playgroud)
您可以使用导航图 xml 文件并将片段的标签设置为参数。然后,在您的父片段中,您可以使用 SafeArgs 传递参数(请按照https://developer.android.com/guide/navigation/navigation-pass-data#Safe-args上的指南设置 SafeArgs)和提供默认值以避免标题为 null 或为空。
<!--this is originating fragment-->
<fragment
android:id="@+id/fragmentA"
android:name=".ui.FragmentA"
tools:layout="@layout/fragment_a">
<action
android:id="@+id/fragmentBAction"
app:destination="@id/fragmentB" />
</fragment>
<!--set the fragment's title to a string passed as an argument-->
<!--this is a destination fragment (assuming you're navigating FragmentA to FragmentB)-->
<fragment
android:id="@+id/fragmentB"
android:name="ui.FragmentB"
android:label="{myTitle}"
tools:layout="@layout/fragment_b">
<argument
android:name="myTitle"
android:defaultValue="defaultTitle"
app:argType="string" />
</fragment>
Run Code Online (Sandbox Code Playgroud)
在原始片段中:
public void onClick(View view) {
String text = "text to pass as a title";
FragmentADirections.FragmentBAction action = FragmentADirections.fragmentBAction();
action.setMyTitle(text);
Navigation.findNavController(view).navigate(action);
}
Run Code Online (Sandbox Code Playgroud)
FragmentADirections 和 FragmentBAction - 这些类是根据您的 nav_graph.xml 文件中的 ID 自动生成的。在“您的操作 ID + 操作”类型类中,您可以找到自动生成的 setter 方法,您可以使用这些方法传递参数
在您的接收目的地,您调用自动生成的类 {您的接收片段 ID}+Args
FragmentBArgs.fromBundle(requireArguments()).getMyTitle();
Run Code Online (Sandbox Code Playgroud)
请参考官方指南 https://developer.android.com/guide/navigation/navigation-pass-data#Safe-args
NavigationUI.setupActionBarWithNavController(this, navController)
Run Code Online (Sandbox Code Playgroud)
不要忘记在导航图中为片段指定android:label。
要返回:
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(navController, null)
}
Run Code Online (Sandbox Code Playgroud)
我花了几个小时尝试做一件非常简单的事情,例如从主片段上的特定项目导航时更改细节片段的栏标题。我爸爸总是对我说:KISS,保持简单,儿子。setTitle() 崩溃了,界面很麻烦,针对最新的片段导航实现,在代码行方面提出了一个(非常)简单的解决方案。在主片段中解析 NavController,获取 NavGraph,找到目标节点,设置标题,最后但并非最不重要的导航到它:
//----------------------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
私人无效navigateToDetail(){
NavController navController = NavHostFragment.findNavController(FragmentMaster.this);
navController.getGraph().findNode(R.id.FragmentDetail).setLabel("Master record detail");
navController.navigate(R.id.action_FragmentMaster_to_FragmentDetail,null);
Run Code Online (Sandbox Code Playgroud)
}
| 归档时间: |
|
| 查看次数: |
9060 次 |
| 最近记录: |