Different toolbar for fragments and Navigation Drawer
Asked Answered
S

5

12

Please, explain to me... I have Navigation Drawer in my Activity and it syncs with Toolbar (like ActionBar). Activity has few fragments and in different fragments I need to use different AppBar modes (parallax in one, simple in another). So, I think that I should set CoordinatorLayout in each frament with AppBar and content.
But how I can replace last toolbar on new to save synchronization with Drawer? Or it's wrong way and I need make it some else?

Strawser answered 26/1, 2016 at 13:41 Comment(0)
U
10

Not sure if my approach is good, but I tried to add this public method to my activity:

public void setToolbar(Toolbar toolbar) {
    if(toolbar != null) {
        setSupportActionBar(toolbar);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();
    } else {
        drawer.setDrawerListener(null);
    }
}

and I added this in all fragments:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ((MainActivity)getActivity()).setToolbar(toolbar);
}

@Override
public void onDestroyView() {
    ((MainActivity)getActivity()).setToolbar(null);
    super.onDestroyView();
}

It's working fine, but I'm not sure if it may cause a memory leak or any other performance issue. Maybe someone can help with it?

Unravel answered 28/2, 2016 at 0:40 Comment(6)
I solved this problem. Just I use DrawerLayout in activity layout and Toolbar in fragment layouts where in onCreateView set Toolbar like ActionBar and synchronize it with DrawerLayout.Strawser
And your solution has not any memory leaks)Strawser
@Шах Would you like to elaborate on how you are syncing with DrawerLayout from fragment onCreateView? Are you re-creating the ActionBarDrawerToggle for every fragment Toolbar? Are you using the DrawerLayout constructor with, or without, Toolbar?Hartnett
@Шах, yes, pls, answer, how have you gotten an application with different toolbars? А то у меня выглядят ужасно.Subclavian
@CoolMind, Просто во фрагменте, где ты определил свой Toolbar в onCreateView установи его как ActionBar и синхронизируй с DrawerLayout так же, как в обычной активити. For English, I don't remeber already how to need to define Toolbar in onCreateView to it can be used like ActionBar with DrawerLayout.Strawser
@Шах, спасибо, добрый человек! I tried to make so, but have the same problem (Toolbar as parallax and usual ActionBar). So I have one activity with DrawerLayout, FrameLayout and NavigationView, all other layouts are inside fragments. But when I replace a fragment or want to have a parallax effect, it doesn't work well.Subclavian
H
5

You can access main DrawerLayout from each Fragment just like the following code:

AppCompatActivity actionBar = (AppCompatActivity) getActivity();
actionBar.setSupportActionBar(toolbar);

DrawerLayout drawer = (DrawerLayout) actionBar.findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            getActivity(), drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
Halfdan answered 25/8, 2016 at 9:0 Comment(1)
Can you describe an activity and fragments? Are all fragments have their own toolbars or use activity's? I have an activity with DrawerLayout and NavigationView, inside it fragments are placed, they contain CoordinatorLayout, AppBarLayout, Toolbar, but it works bad, toolbars don't look as I want when change fragments.Subclavian
F
1

If you want to use appbar(toolbar) that you specified in navigation drawer in different fragments with, for example different options menu items, you could make a public method in Main Activity where you specified your navigation drawer logic.

public void setToolbar(Toolbar toolbar, String title){
    AppCompatActivity actionBar = this;
    actionBar.setSupportActionBar(toolbar);

    DrawerLayout drawer = (DrawerLayout)actionBar.findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toogle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
    drawer.addDrawerListener(toogle);
    toogle.setDrawerIndicatorEnabled(true);
    toogle.syncState();
    if(toolbar != null)
        toolbar.setTitle(title);
}


Now you can use this method in your fragments to access the main toolbar and override it with your custom title, options menu... You can do this by creating a new toolbar variable in your fragment and then inflate it in onCreateView() method like this
toolbarFragment = (Toolbar)getActivity().findViewById(R.id.toolbar);

R.id.toolbar is the id of a toolbar that you specified in your layout file and it is the same id that you used in your main activity for the main toolbar.


Now you can call the method setToolbar(Toolbar toolbar, String title) in fragment like this
((MainActivity)getActivity()).setToolbar(toolbarFragment, "Some title");


If you want to use options menu for this fragment you have to call
setHasOptionsMenu(true);

in fragments onCreate() or onCreateView() methods. After that you can override method onCreateOptionsMenu() like this

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.custom_menu1, menu);
}

You can repeat this procedure for other fragments in your navigation drawer as well. Although it worked for me, I don't know if this violates activities or fragments lifecycle or causes memory leeks.

Forceps answered 15/12, 2016 at 18:12 Comment(2)
No-no, guy, it wasn't a problem. I needed to make a very flex and complex GUI for different fragments. It required full access to appbarStrawser
Just I had fragments with parallax header, navigation path (like in some file manger) and etc.Strawser
P
0

I have the same problem. I wanted to add CollapsingToolbar only in the main fragment. By removing the toolbar from Activity, I lost the hamburger button and the connection to drawerLayout. To solve this problem, I didn't delete the Toolbar in activity and made it transparent. And for each fragment, I created my own custom toolbar. In the end, I have a hamburger button linked to the Drawer and a well-functioning CollapsingToolbar. I know it's a crutch. But I couldn't find another way

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.MainActivity">

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

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

    <include
        android:id="@+id/include"
        layout="@layout/content_main"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

To make the AppBar completely invisible, I added

AppBarLayout appBarLayout = findViewById(R.id.appbar);
appBarLayout.setOutlineProvider(null);

This works for Android with sdk version 21.

Proportionate answered 7/8, 2020 at 13:19 Comment(0)
P
-3

If you are using DrawerLayout and NavigationView for your navigation drawer, best solution according to me would be to use individual DrawerLayout for each of the fragment layouts and use the AppBarLayout in the body of the DrawerLayout differently for each of the fragments.

Photoelasticity answered 26/1, 2016 at 13:51 Comment(3)
Is this the only solution? I will need to re-attach almost all view hierarchyStrawser
You must understand that you are attempting to change a body view and not the parent view because the AppBarLayout remains embedded inside the body the DrawerLayout. So the best practice would be to redeclare the layout. If your NavigationView is identical for all fragments, you can write it in a separate xml layout file and use <include layout="@layout/navigation_layout_name"> which can shorten your code.Photoelasticity
Well, thank you! Just I think that this solution can take much time on fragment switching. But I will use it.Strawser

© 2022 - 2024 — McMap. All rights reserved.