Search code examples
androidnavigationnavigation-drawerandroid-toolbar

Navigation UI Architecture with collapsing toolbar in fragment


I am building my app with the modern Architecture Components.

Here is my main activity XML

<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/relativeLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/main_app_bar_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <com.google.android.material.appbar.MaterialToolbar
                android:id="@+id/main_tool_bar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:theme="@style/MaterialTheme"
                style="@style/Widget.MaterialComponents.Toolbar.Primary"
                app:titleTextColor = "@android:color/white"
                />

        </com.google.android.material.appbar.AppBarLayout>

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

    </RelativeLayout>


    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@drawable/gradient_background"
        android:theme="@style/Theme.Design"
        app:itemTextColor="@android:color/white"
        app:menu="@menu/drawer_menu" />

</androidx.drawerlayout.widget.DrawerLayout>

Here is my Main activity java file of how i am setting up my nav controller


        DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);

        NavigationView navigationView = findViewById(R.id.navigation_view);

        MaterialToolbar mainToolBar = findViewById(R.id.main_tool_bar);

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);

        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(R.id.wallet_fragment)
                .setOpenableLayout(drawerLayout)
                .build();

        NavigationUI.setupWithNavController(mainToolBar, navController, appBarConfiguration);

Here is my fragment xml with the collapsing toolbar


<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"
    tools:context=".fragments.WalletFragment">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleTextAppearance="@style/TextAppearance.AppCompat.Large"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:padding="5dp">

                <de.hdodenhof.circleimageview.CircleImageView
                    android:id="@+id/imv_display_pic"
                    android:layout_width="120dp"
                    android:layout_height="120dp"
                    android:layout_alignParentStart="true"
                    android:layout_alignParentLeft="true"
                    android:layout_centerInParent="true"
                    android:src="@drawable/ic_launcher"
                    app:civ_border_color="@android:color/white"
                    app:civ_border_width="2dp" />

                <RelativeLayout
                    android:id="@+id/relative_layout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_toEndOf="@+id/imv_display_pic"
                    android:layout_toRightOf="@+id/imv_display_pic">

                    <TextView
                        android:id="@+id/tv_wallet_balance"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:layout_marginLeft="10dp"
                        android:text="Ksh 1000"
                        android:textAppearance="@style/TextAppearance.AppCompat.Display1"
                        android:textColor="@android:color/white" />

                    <TextView
                        android:id="@+id/tv_display_wallet_balance"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_below="@id/tv_wallet_balance"
                        android:layout_marginStart="10dp"
                        android:layout_marginLeft="10dp"
                        android:text="Wallet Balance"
                        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

                </RelativeLayout>

            </RelativeLayout>

            <com.google.android.material.appbar.MaterialToolbar
                android:id="@+id/wallet_tool_bar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:title="Username" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal">

            <com.google.android.material.button.MaterialButton
                android:id="@+id/btn_add_money"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="2dp"
                android:layout_marginLeft="2dp"
                android:layout_marginTop="2dp"
                android:layout_marginBottom="2dp"
                android:text="Add Money"
                android:textColor="@android:color/white"
                android:theme="@style/ButtonsTheme"
                app:icon="@drawable/ic_add_money"
                app:iconTint="@android:color/white"
                android:textAllCaps="false"/>

            <com.google.android.material.button.MaterialButton
                android:id="@+id/btn_withdraw_money"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="2dp"
                android:layout_marginLeft="2dp"
                android:layout_marginTop="2dp"
                android:layout_marginBottom="2dp"
                android:layout_toEndOf="@+id/btn_add_money"
                android:layout_toRightOf="@+id/btn_add_money"
                android:text="Withdraw Money"
                android:textColor="@android:color/white"
                android:theme="@style/ButtonsTheme"
                app:icon="@drawable/ic_withdraw"
                app:iconTint="@android:color/white"
                android:textAllCaps="false" />

        </RelativeLayout>

    </androidx.core.widget.NestedScrollView>


</androidx.coordinatorlayout.widget.CoordinatorLayout>

The issue am having is how will i make the material toolbar in the collapsing toolbar to be the main toolbar when the fragment is loaded right now its showing two toolbars the one in the main activity and the one in the fragment .

I have tried implementing the solution here: https://developer.android.com/guide/navigation/navigation-ui#support_app_bar_variations

Here is how i tried to implement in fragment java class

    NavController navController = Navigation.findNavController(view);
    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph()).build();
    MaterialToolbar walletToolBar = view.findViewById(R.id.wallet_tool_bar);

    NavigationUI.setupWithNavController(
            walletToolBar , navController, appBarConfiguration);

I have tried that but its still showing the toolbar from the main activity and from the fragment


Solution

  • First we set up theme in themes.xml or styles.xml

        <style name="Theme.AppTheme" parent="Theme.MaterialComponents.DayNight">
            <!-- Primary brand color. -->
            <item name="colorPrimary">@color/primaryColor</item>
            <item name="colorPrimaryVariant">@color/primaryDarkColor</item>
            <item name="colorOnPrimary">@color/primaryLightColor</item>
            <!-- Secondary brand color. -->
            <item name="colorSecondary">@color/secondaryColor</item>
            <item name="colorSecondaryVariant">@color/secondaryDarkColor</item>
            <item name="colorOnSecondary">@color/secondaryLightColor</item>
            <!-- Status bar color. -->
            <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
            <!-- Customize your theme here. -->
            <item name="actionBarTheme">@style/ActionBarTheme</item>
    
        </style>
    
        <style name="ActionBarTheme" parent="Theme.MaterialComponents.DayNight">
    
            <item name="colorPrimary">@color/primaryColor</item>
            <item name="colorPrimaryVariant">@color/primaryDarkColor</item>
            <item name="colorOnPrimary">@color/primaryLightColor</item>
            <!-- Secondary brand color. -->
            <item name="colorSecondary">@color/secondaryColor</item>
            <item name="colorSecondaryVariant">@color/secondaryDarkColor</item>
            <item name="colorOnSecondary">@color/secondaryLightColor</item>
            <!-- Status bar color. -->
            <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
    
            <!--Toolbar text color-->
            <item name="android:textColorPrimary">@android:color/white</item>
    
            <!-- action menu item icon color -->
            <item name="colorControlNormal">@android:color/white</item>
    
        </style>
    
    

    Then in Manifest inside application tag

    
    android:theme="@style/Theme.AppTheme"
    
    

    MainActivity XML Implementation

    <androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <fragment
                android:id="@+id/nav_host_fragment"
                android:name="androidx.navigation.fragment.NavHostFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:defaultNavHost="true"
                app:navGraph="@navigation/navigation_graph"/>
    
        </RelativeLayout>
    
        <!--app:headerLayout="@layout/nav_header"-->
        <com.google.android.material.navigation.NavigationView
            android:id="@+id/navigation_view"
            android:layout_width="230dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@drawable/nav_view_background"
            android:fitsSystemWindows="true"
            app:itemTextColor="@android:color/white"
            app:itemIconTint="@android:color/white"
            android:theme="@style/Theme.AppCompat.DayNight"
            app:menu="@menu/drawer_menu">
    
        </com.google.android.material.navigation.NavigationView>
    
    
    </androidx.drawerlayout.widget.DrawerLayout>
    
    

    MainActivity java file implementation

    
        DrawerLayout drawerLayout;
        NavigationView navigationView;
        AppBarConfiguration appBarConfiguration;
        NavController navController;
    
        ActionBarDrawerToggle navDrawerToggle;
    
       // Inside onCreate method 
    
            drawerLayout = findViewById(R.id.drawer_layout);
    
            navigationView = findViewById(R.id.navigation_view);
    
            navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    
            navDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, "open", "close");
    
            drawerLayout.addDrawerListener(navDrawerToggle);
            navDrawerToggle.setDrawerIndicatorEnabled(true);
            navDrawerToggle.syncState();
    
            appBarConfiguration = new AppBarConfiguration.Builder(R.id.nav_wallpapers_fragment)
                    .setOpenableLayout(drawerLayout)
                    .build();
    
            NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    
            NavigationUI.setupWithNavController(navigationView, navController);
    
    

    Fragment Having the Collapsing Toolbar XML implementation

    <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:background="@color/colorWhiteShade"
        tools:context=".fragments.WallpaperDetailsFragment">
    
        <com.google.android.material.appbar.AppBarLayout
                android:id="@+id/app_bar_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    
        <!--        Change height of the collapsing toolbar here-->
                <!--To make the expanded title appearance to transparent-->
        <!--        app:expandedTitleTextAppearance="@android:color/transparent"-->
                <com.google.android.material.appbar.CollapsingToolbarLayout
                    android:id="@+id/collapsing_toolbar_layout"
                    android:layout_width="match_parent"
                    android:layout_height="200dp"
                    app:contentScrim="?attr/colorPrimary"
                    android:fitsSystemWindows="true"
                    app:layout_scrollFlags="scroll|exitUntilCollapsed"
                    app:expandedTitleTextAppearance="@android:color/transparent">
    
                    <ImageView
                        android:id="@+id/imageview"
                        android:layout_width="match_parent"
                        android:layout_height="200dp"
                        android:scaleType="centerCrop"
                        android:contentDescription="@string/wallpaper_collapsing_toolbar"/>
    
                    <androidx.appcompat.widget.Toolbar
                        android:id="@+id/toolbar"
                        android:layout_width="match_parent"
                        android:layout_height="?attr/actionBarSize"
                        app:layout_collapseMode="pin"
                        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                        app:title="Toolbar Title"/>
    
                </com.google.android.material.appbar.CollapsingToolbarLayout>
    
            </com.google.android.material.appbar.AppBarLayout>
    
        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clipToPadding="false"
            android:scrollbars="none"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">
    
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
          
                // Create your views here
    
            </RelativeLayout>
    
        </androidx.core.widget.NestedScrollView>
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    
    

    Fragment having the collapsing toolbar

        AppBarLayout appBarLayout;
    
        CollapsingToolbarLayout collapsingToolBarLayout;
    
        Toolbar toolbar;
    
        DrawerLayout drawerLayout;
    
        // In onCreate method
    
         @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            Objects.requireNonNull(((MainActivity) requireActivity()).getSupportActionBar()).hide();
    
        }
    
       // In onViewCreated method 
    
            appBarLayout= view.findViewById(R.id.app_bar_layout);
            CollapsingToolbarLayout = view.findViewById(R.id.collapsing_toolbar_layout);
            toolbar= view.findViewById(R.id.toolbar);
    
             AppBarConfiguration appBarConfiguration =
                    new AppBarConfiguration.Builder(navController.getGraph()).build();
    
            NavigationUI.setupWithNavController(
                    toolbar, navController, appBarConfiguration);
    
            NavigationUI.setupWithNavController(CollapsingToolbarLayout , toolbar, navController);