新导航组件的提议实践在 I/O 上展示了以下模板和提议的理念:
- 一个应用程序的一个活动
- Activity 包含工具栏和底部导航栏
一个典型的应用程序通常有一个带有 CollapsingToolbar 的详细视图。在那种架构下如何构建它?
- 将工具栏移动到每个片段 XML?
- 以编程方式实现折叠工具栏?
- 将细节片段移动到自己的活动中(无论如何它可能会使用自己的深层链接)并“打破”哲学?
新导航组件的提议实践在 I/O 上展示了以下模板和提议的理念:
一个典型的应用程序通常有一个带有 CollapsingToolbar 的详细视图。在那种架构下如何构建它?
一个典型的应用程序通常有一个带有 CollapsingToolbar 的详细视图。在那种架构下如何构建它?
好问题!我也为此苦苦挣扎了一下,得出的结论是应该有一个带有 NavHostFragment 的 Activity,理想情况下,没有别的。这为您提供了最大的灵活性来显示(或不显示)每个屏幕所需的任何内容。重要的是,确保您的主题删除了 ActionBar:
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
这导致你的下一个问题......
将工具栏移动到每个片段 XML?
在我看来,是的!您通常使用 ActionBar 的一切都可以通过工具栏完成。下面是一个简短的片段,它显示了如何使用工具栏来执行您过去使用 ActionBar 的最重要的事情(向上导航、标题、选项菜单等......):
toolbar.apply {
setNavigationOnClickListener { findNavController().navigateUp() }
setTitle(R.string.toolbar_title)
inflateMenu(R.menu.fragment_menu)
setOnMenuItemClickListener(::onMenuItemClick)
}
以编程方式实现折叠工具栏?
这取决于您到底要做什么,但很可能没有必要这样做。您可以将 AppBarLayout、CollapsingToolbarLayout 和 Toolbar 拖放到您的布局中并像平常一样使用它们。给你的 AppBarLayout 一个 ActionBar 主题覆盖。这是一个例子:
<?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:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentScrim="@color/primary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_up_white"/>
...
将细节片段移动到自己的活动中(无论如何它可能会使用自己的深层链接)并“打破”哲学?
不需要上面的,对吧?这是一种足够灵活的方法,可以在一个导航图中轻松容纳多个级别,并且仍然能够自定义图中每个目的地的外观和行为(包括类似于 ActionBar 的功能)。
尝试
appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
if(expandToolbar){
appBarLayout.setExpanded(true,true);
}else{
appBarLayout.setExpanded(false,true);
}
这是某些片段的 CollapsingToolbarLayout 上的常用链接 禁用扩展
对于其他想要更改工具栏某些部分的人来说,您应该在单独的 XML 中编写自定义工具栏视图,并尝试在您的详细信息片段中以语法方式扩展自定义视图,然后隐藏旧工具栏的未使用元素(如果有)。
setSupportActionBar(toolbar);
View logo = getLayoutInflater().inflate(R.layout.view_logo, null);
toolbar.addView(logo);
这就是你如何隐藏不需要的视图
for (int i = 0; i < toolbar.getChildCount(); ++i) {
View child = toolbar.getChildAt(i);
// here u can hide all text views for example.
if (child instanceof TextView) {
child.setVisibility(View.GONE );
}
}
这种方式比写两个活动好多了
假设我们有
您的应用程序所需的工具栏的所有可能外观都应在该单个工具栏中实现,并且可以控制为当前活动的片段。为了不违反依赖倒置原则,所有需要 Activity 工具栏中的功能的 Fragment 都必须实现一个接口。您可以使用 OnBackStackChangedListener 检查视图的更新
getFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
Fragment visibleFragment = ...
if(visibleFragment instanceof ToolbarControlFragment) {
if(visibleFragment.shouldExpandToolbar()) {
// set AppBarLayout expanded state
}
// ...
}
}
}
);
当 Fragment 需要 OptionsMenu 时,您可能还记得这个原则。
我通常建议只使用一个由活动控制的底部导航栏和片段中的几个工具栏。这降低了复杂性并使应用程序的组件更加独立。