首页 文章

如何使用导航架构组件在应用栏中设置 Headers

提问于
浏览
1

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

要清除我的问题,让's have an example, where, I' ve设置一个简单的应用程序, MainActivity 托管导航主机控制器, MainFragment 有一个按钮,单击按钮它会转到 DetailFragment .

堆栈溢出中另一个multiple app bars问题的相同代码 .

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>

所以当启动我的应用程序时, the title is "MainActivity" . 像往常一样,它显示 MainFragment ,其中包含要转到 DetailFragment 的按钮 . 在 DialogFragment 中,我将 Headers 设置为:

getActivity().getSupportActionBar().setTitle("Detail");

First Problem: 因此,单击 MainFragment 上的按钮转到 DetailFragment ,它会转到那里, Headers 会变为"Detail" . 但是点击后退按钮, title changes to "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");
}

现在,从 DetailFragment 返回到 MainFragment , Headers 更改为"Hello" . 但是 second problem ,当我关闭应用程序并重新开始时, Headers 会变回"MainActivity"虽然它应该显示"Hello",但是,知道吗?

好的,然后在 MainFrgment 中添加 setTitle("Hello") 也不起作用 . 例如,活动开始, Headers 为"Hello",转到 DetailsFragment 并再次按后退按钮, Headers 返回"fragment_main" .

唯一的解决方案是在 MainFragment 中同时包含 setTitle("Hello")Navigation.findNavController(view).getCurrentDestination().setLabel("Hello") .

那么使用导航组件显示片段 Headers 的正确方法是什么?

1 回答

  • 1

    这实际上是因为:

    android:label="fragment_main"
    

    您在xml中设置了哪个 .

    那么使用导航组件显示片段 Headers 的正确方法是什么?

    setTitle() 此时起作用 . 但是,因为您为那些 Fragment 设置了标签,所以在重新创建 Activity 时它可能会再次显示标签 . 该解决方案可能会删除 android:label 然后使用代码执行您的操作:

    getActivity().getSupportActionBar().setTitle("yourtitle");
    

    要么:

    ((AppCompatActivity) getActivity()).getSupportActionBar().setSubtitle();
    

    onCreateView() .


    Found a workaround:

    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")
    

    看看这个:Dynamic ActionBar title from a Fragment using AndroidX Navigation

相关问题