如何使用导航架构组件在应用栏中设置标题 [英] How to set title in app bar with Navigation Architecture Component

查看:63
本文介绍了如何使用导航架构组件在应用栏中设置标题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用导航架构组件,现在在设置标题时遇到了困难.如何以编程方式设置标题以及其工作方式?

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"

但是您应该使用的首选方式是A​​PI 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆