14

In my application I have a collapsing Toolbar. If I start a specific Fragment I want to collapse the Toolbar so it behaves like a "normal" one and that the user can not expend it by himself. Here is my layout which I use for my Toolbar:

<android.support.design.widget.AppBarLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/appBarLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:contentScrim="?attr/colorPrimary"
        app:expandedTitleMarginEnd="64dp"
        app:expandedTitleMarginStart="48dp"
        app:titleEnabled="false"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            android:src="@drawable/drawer_background"
            app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
            android:layout_width="match_parent"
            android:layout_height="172dp"
            android:scaleType="centerCrop"
            app:layout_collapseMode="parallax"
            android:minHeight="100dp" />

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolBar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin"
            app:layout_scrollFlags="scroll|enterAlways" />

    </android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>

I also can collapse the layout from code like so:

appBarLayout.setExpanded(false, false);

final AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();
params.setScrollFlags(0);
collapsingToolbarLayout.setLayoutParams(params);

But this does not help. If the user swipes down from the Toolbar it will expand.

Do you have any ideas why?

Talha
  • 871
  • 8
  • 30
Cilenco
  • 6,264
  • 15
  • 62
  • 128
  • How about setting the `AppBarLayout` height programmatically, so that it matches the height of your Toolbar? That way it would have nowhere to expand to. – PPartisan Mar 08 '16 at 09:31
  • There seems to be a mess with scroll flags in ImageView and Toolbar in your layout. Try to remove them too. – Ilya Polenov Mar 08 '16 at 09:35
  • @IlyaPolenov I changed both to `scroll|enterAlways` but this do not change anything. Do you mean something else? – Cilenco Mar 09 '16 at 08:16
  • Try collapsingToolbarLayout.requestLayout(); method after applying these flags could help .. – Jayant Arora Mar 15 '16 at 07:44

6 Answers6

19

The core problem is that there is no CollapsingToolbarLayout.lock(); method up until now (v23.2.1 of support design). Hopefully, this feature will be included in a future version. Until then, I'm suggesting the following workaround:

You can collapse and lock your toolbar with:

appbar.setExpanded(false,false);
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
lp.height = (int) getResources().getDimension(R.dimen.toolbar_height);

and unlock it with:

 CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
 lp.height = (int) getResources().getDimension(R.dimen.nav_header_height);

However, with the above code a problem occurs:

when forcefully collapsing CoordinatorLayout the title of our Toolbar is gone and CollapsingToolbarLayout.setTitle(CharSequence title); no longer works. To fix that we add a TextView in our Toolbar and manipulate its visibility accordingly. (we want it "gone" in a fragment that has its toolbar 'unlocked' and "visible" in a fragment that has its toolbar 'locked'.

We have to set TextView's android:textAppearance to be the same with CollapsingToolbarLayout's app:collapsedTitleTextAppearance to be consistent and avoid disrupting the user with different toolbar text sizes and colors.

In summary, with an interface like this:

public interface ToolbarManipulation {
    void collapseToolbar();
    void expandToolbar();
    void setTitle(String s);
}

implemantations like these:

@Override
    public void collapseToolbar(){
        appbar.setExpanded(false,false);
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
        lp.height = (int) getResources().getDimension(R.dimen.toolbar_height);
        toolbarCollapsedTitle.setVisibility(View.VISIBLE);
    }

    @Override
    public void expandToolbar() {
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
        lp.height = (int) getResources().getDimension(R.dimen.nav_header_height);
        toolbarCollapsedTitle.setVisibility(View.GONE);
    }

    @Override
    public void setTitle(String s) {
        collapsingToolbarLayout.setTitle(s);
        toolbarCollapsedTitle.setText(s);
        collapsingToolbarLayout.invalidate();
        toolbarCollapsedTitle.invalidate();
    }

and main xml like this:

....
  <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:collapsedTitleTextAppearance="@style/CollapsedAppBar"

            >
                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:background="?attr/colorPrimary"
                    app:layout_collapseMode="pin"
                    app:popupTheme="@style/AppTheme.PopupOverlay"
                    >
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="?attr/actionBarSize"
                        android:visibility="gone"
                        android:layout_gravity="center_vertical|start"
                        android:gravity="center_vertical|start"
                        android:id="@+id/toolbar_collapsed_title"
                        android:textAppearance="@style/CollapsedAppBar"
                        />
                </android.support.v7.widget.Toolbar>
        </android.support.design.widget.CollapsingToolbarLayout>
......

you can lock and unlock your Toolbar as you like. Your fragments should call these functions in their onResume();

I've uploaded an example implementation here.

Note: This is just a workaround and obviously not the cleanest solution. We're waiting for a newer version of com.android.support to resolve this.

Sevle
  • 3,014
  • 2
  • 17
  • 28
  • 1
    Nice thank you for this great answer. I hoped that someone refers to the support library and their limitation so thank you for this detailed answer! – Cilenco Mar 15 '16 at 21:30
  • what is default toolbar_height ? @Sevle – Sid May 03 '16 at 11:46
  • 48dp for landscape and 56dp for portrait, source: https://www.google.com/design/spec/layout/metrics-keylines.html – Sevle May 05 '16 at 16:07
  • There is a small issue the text of the title in the toolbar jump a bit when you pressback, also I suggest to change it's style to inherit from @style/TextAppearance.AppCompat.Widget.ActionBar.Title instead of @android:style/TextAppearance.Medium – Anton Makov Feb 17 '18 at 19:11
  • Thank you man )) spent like a day to solve this problem finally did it with ur solution perfect) working as expected – Aliy Mar 23 '18 at 15:42
13

I'm not exactly sure if this is what you are looking for

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); 
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior(); 
behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
    @Override
    public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
        return false;
    } 
});
gaara87
  • 2,077
  • 3
  • 20
  • 41
2

Try to change the height of the AppBar. It works for me.

public void lockAppBar() {
    int appbarHeight = (int)getResources().getDimension(R.dimen.your_fixed_appbar_height);
    getView().findViewById(R.id.my_appbar).getLayoutParams().height = appbarHeight; 
}
arsent
  • 5,565
  • 2
  • 30
  • 29
2

Do findViewById(R.id.image_view).setVisibility(View.GONE); where image_view is the id of the imageView in the collapsing toolbar. But if you want to do it for a specific fragment I suggest calling the same using fragment- activity communication.

Vaibhav Sharma
  • 2,113
  • 1
  • 15
  • 21
2

None of the provided solutions worked for me except this one. With this solution, i can easily manage the state of collapsing toolbar. This will prevent expanding/enable collapsing of collapsing toolbar and set title for it.

public void lockAppBar(boolean locked,String title) {
    if(locked){
        appBarLayout.setExpanded(false, true);
        int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics());
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appBarLayout.getLayoutParams();
        lp.height = px;
        appBarLayout.setLayoutParams(lp);
        collapsingToolbarLayout.setTitleEnabled(false);
        toolbar.setTitle(title);
    }else{
        appBarLayout.setExpanded(true, false);
        appBarLayout.setActivated(true);
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
        lp.height = (int) getResources().getDimension(R.dimen.toolbarExpandHeight);
        collapsingToolbarLayout.setTitleEnabled(true);
        collapsingToolbarLayout.setTitle(title);
    }

}
Kemal
  • 86
  • 8
1

Well try setting some parameters to toolBar, tabLayout programatically, I have ViewPager changing flags on onPageSelected(int)

        @Override
        public void onPageSelected(int position) {
            AppBarLayout.LayoutParams params = new AppBarLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            if (position == 3) {//listen for scrolls only for Fragment 3
                params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
                toolBar.setLayoutParams(params);//hide as per scroll
                params = new AppBarLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
                tabLayout.setLayoutParams(params);//always visible
            } else {
                appBarLayout.setExpanded(false, true);
                params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED);
                toolBar.setLayoutParams(params);//don't listen to scrolls
                tabLayout.setLayoutParams(params);//dont listen to scrolls
            }
        }

Use/Set above flags as you required. AppBarLayout.LayoutParams

Bharatesh
  • 8,375
  • 3
  • 34
  • 61