导航组件:条件导航中的工具栏问题

Navigation Component: Toolbar issue in conditional navigation

根据 navigation priciples 您的应用程序中的第一个目的地应该是您的用户在 signup/login 或任何其他条件导航后启动应用程序时通常会看到的屏幕,我将其称为起始目的地'homeFragment'.

遵循这一原则并在阅读 conditional navigation by Maria Neumayer 上的 post 后,我在经历条件导航流程时遇到了工具栏和后退导航的一些问题。

我正在使用一个带有 ConstraintLayout、工具栏和 NavHostFragment 的 activity 构建应用程序:

<android.support.constraint.ConstraintLayout
    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"
    tools:context=".ui.activities.NavigationTestActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:navGraph="@navigation/nav_graph"
        app:defaultNavHost="true"
        />

</android.support.constraint.ConstraintLayout>

主图看起来像这样,以家庭目的地作为起始目的地,连接到详细信息片段的操作(此操作由按钮触发)和使用嵌套图实现的条件导航:

Main Graph

我将这个嵌套图称为 welcomeGraph,它包括登录或注册的屏幕,您可以在这里看到它:

Welcome Nested Graph

在 homeFragment onResume 中,我检查 login/signup 是否已完成(由存储在 sharedPrefs 中的虚拟布尔值确定),如果没有,我将启动 signup/login.[=15 的欢迎嵌套图=]

在登录目标中,我有一个 'Completed' 按钮,它将 sharedPrefs 中的虚拟布尔值设置为 true 并触发一个操作 popToWelcomeGraph(包括),它应该关闭整个嵌套图并将我带回 homeFragment(这行得通)。

问题 - 嵌套图表中的工具栏问题:

由于欢迎图是在用户登陆应用程序后立即启动的,因此工具栏不应在该嵌套图的第一个目的地显示 back/up 箭头,而应该让人感觉它是第一个目的地屏幕上的应用程序,然后点击返回应该退出应用程序。

问题:是否可以在此处更改工具栏以模拟嵌套图中的第一个屏幕是应用程序中的第一个屏幕,直到 login/signup 完成?这是一种不好的做法吗?

您必须实现如下所示的通信器接口

interface ActivityCommunicator {
    void alterToolbar();
}

并将其实施到您的 activity class,如下所示

class HomeActivity extends AppCompatActivity implements ActivityCommunicator {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Activity code
}

@Override
public void alterToolbar() {
    ActionBar actionBar = getSupportActionBar();
    // False to hide back button and true to show it
    actionBar.setDisplayHomeAsUpEnabled(false);
}

}

从你的片段中你可以像下面这样称呼它

public class MainFragment extends Fragment {

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    ActivityCommunicator activityCommunicator = (ActivityCommunicator) getActivity();
    activityCommunicator.alterToolbar();
    // Fragment code
    return super.onCreateView(inflater, container, savedInstanceState);
}

}

您可以根据需要更改 alterToolbar() 实现

我最近通过创建 AppBarConfiguration 并使用该配置设置工具栏解决了这个问题。 AppBarConfiguration 将顶级目标 ID 作为参数。话虽这么说,你可以做类似

private lateinit var appBarConfiguration: AppBarConfiguration
...

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  appBarConfiguration = AppBarConfiguration(setOf(R.id.homeFragment,R.id.welcomeFragment))
  findViewById<Toolbar>(R.id.toolbar).setupWithNavController(navController, appBarConfiguration)
}

这样后退按钮就不会显示在顶级片段上。