带导航组件的单个活动:如何处理不同的AppBar /主题

Dan*_*ato 9 android-layout android-fragments android-architecture-navigation

自Google I/O宣布之后不久,我一直在使用新的导航组件,并且也开始尽可能地接受单项活动.

单一活动允许我在视图之间共享ViewModel以获得非常棒的体验,如果我没有被迫,我真的不想回到多活动.

但是有一些东西阻碍了:AppBar/Themes(状态栏)到单一活动的概念.

这是我正在进行的设计的一部分:

AppBar设计在不同的部分

正如您所看到的,Actionbar /状态栏的外观有不同的要求.

  1. 这是一个带有标准动作栏的简单抽屉
  2. 图像在半透明状态栏下的经典细节,CollapsingToolbarLayout在向上滚动时应该用于变成标准动作栏
  3. 在这种情况下,它是非标准的操作栏,我称之为"浮动工具栏",因为它没有扩展到屏幕的全部,并包含已经扩展的SearchView/EditText
  4. 带标签的相当标准的AppBar

离开单项活动所产生的问题清单:

  • 不能ViewModel在活动之间分享
  • 重复使用已在另一个活动导航图中定义的部分的复杂导航必须复制/移动到专用活动中
  • 返回导航"重建"在活动之间不起作用

如果可能的话,这些是我想要避免的问题,但是你们如何在导航组件的单一活动中管理这些情况.任何的想法?

Raj*_*shi 1

我也有同样的想法,但一直没有时间做一些实验。所以这不是一个解决方案,而是一个实验,我想用另一个视图替换一个视图,这里是用包含 ImageView 的工具栏替换工具栏。

因此,我使用“基本活动”模板创建了一个新应用程序。然后在图表中创建两个目的地:Home 和destination。最后,为工具栏创建了另一个布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="?actionBarSize">

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@mipmap/ic_launcher_round" />

</androidx.appcompat.widget.Toolbar>
Run Code Online (Sandbox Code Playgroud)

activity_main.xml具有:

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        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>

    ...
Run Code Online (Sandbox Code Playgroud)

然后在 Activity 中,当然取决于设置,但假设我想设置一个带有工具栏的支持操作栏:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = findViewById(R.id.toolbar);
    Toolbar toolbar2 = (Toolbar) getLayoutInflater().inflate(R.layout.destination_toolbar, null);

    AppBarLayout appBarLayout = findViewById(R.id.appbar_layout);

    navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph())
            .build();

    navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
        switch (destination.getId()) {
            case R.id.homeFragment:
                appBarLayout.removeAllViews();
                appBarLayout.addView(toolbar);
                setSupportActionBar(toolbar);
                toolbar.setTitle("Home Fragment");
                NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
                break;
            case R.id.destinationFragment:
                appBarLayout.removeAllViews();
                appBarLayout.addView(toolbar2);
                setSupportActionBar(toolbar2);
                toolbar2.setTitle("");
                NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
                break;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

因此,这是有效的,随着目的地的增长和新工具栏/任何其他视图的添加,它变得有些难看。

PS正如我之前所说,这只是一个实验,如果有人有更好的解决方案,请发布新答案。