Edu Yubero
Edu Yubero

Reputation: 711

Navigation Component: Toolbar issue in conditional navigation

According to the navigation priciples the first destination in your app should be the screen your users would normally see when they launch the app after signup/login or any other conditional navigation, I called that start destination 'homeFragment'.

Following this principle and after reading the post on conditional navigation by Maria Neumayer I am facing some issues with the Toolbar and the back navigation when going through the conditional navigation flows.

I am architecting the app using one single activity with a ConstraintLayout, a Toolbar and the NavHostFragment:

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

The main graph looks like this with the home destination as start destination, connected with an action to a detail fragment (this action is triggered from a button) and a conditional navigation implemented using a nested graph:

Main Graph

I called this nested graph welcomeGraph and it includes the screens for login or signup, you can see it here:

Welcome Nested Graph

In the homeFragment onResume I check if the login/signup has been completed (determined by a dummy boolean stored in sharedPrefs) and if not I launch the welcome nested graph for signup/login.

In the login destination I have a 'Completed' button which sets the dummy boolean in sharedPrefs as true and triggers an action popToWelcomeGraph (inclusive) which should close the whole nested graph and take me back to the homeFragment (this works).

PROBLEM - Toolbar issue in nested graph:

As the Welcome graph is lauched inmediatelly after user lands in the app, the toolbar should not display a back/up arrow in the first destination of that nested graph, instead it should feel as if it was the first screen on the app, and tapping back should quit the app.

QUESTION: Is it possible to alter the Toolbar here to simulate the first screen in the nested graph is the first screen in the app until the login/signup is completed? Would this be a bad practice?

Upvotes: 2

Views: 778

Answers (2)

iskae
iskae

Reputation: 121

I have recently solved this issue by creating an AppBarConfiguration and setting up the toolbar with that configuration. The AppBarConfiguration takes in the top level destination ids as parameter. With that being said, you can do something like

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

This way the back button won`t be shown on top level fragments.

Upvotes: 3

SSB
SSB

Reputation: 1034

You have to implement communicator interface like below

interface ActivityCommunicator {
    void alterToolbar();
}

and implement it to your activity class like below

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);
}

}

and from your fragment you can call it like below

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);
}

}

You can change alterToolbar() implementation as per your need

Upvotes: 1

Related Questions