How to disable scrolling of AppBarLayout in CoordinatorLayout?
D

5

30

I have MapFragment with parallax effect inside AppBarLayout:

enter image description here

I want to disable scrolling on AppBarLayout, because it is not possible to move across map, since touch evenys on the map are always handled as scroll events. I would like to handle collapsing of AppBarLayout by scrolling RecyclerView only, which is on the bottom of the screen.

This is my xml:

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_collapseMode="parallax"
            android:fitsSystemWindows="true">

            <fragment
                android:id="@+id/map"
                android:name="com.androidmapsextensions.SupportMapFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </FrameLayout>

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="73dp"
            app:contentInsetLeft="0dp"
            app:contentInsetStart="0dp"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

            <include
                android:id="@+id/search_bar"
                layout="@layout/layout_searchbar" />
        </android.support.v7.widget.Toolbar>

        <View
            android:id="@+id/toolbar_shadow"
            android:layout_width="match_parent"
            android:layout_height="3dp"
            android:layout_below="@id/search_bar"
            android:layout_gravity="bottom"
            android:background="@drawable/toolbar_dropshadow"
            android:visibility="gone" />
    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>


<RecyclerView
    android:id="@+id/farm_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

Thank you for the response.

Disillusionize answered 5/12, 2015 at 17:25 Comment(1)
Where is your CoordinatorLayout?Wicks
S
68

I'm not sure I got it, but I think you are looking for a DragCallback.

The DragCallback interface allows to choose whether the sibling scrolling view should be controlled by scrolls onto the AppBarLayout.

You can define one by calling:

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

By always returning false, your scrolling view will not be controlled by the ABL any longer.

Note: before calling this you should check that ViewCompat.isLaidOut(appBarLayout), otherwise params.getBehavior() will return null.

Smallsword answered 5/12, 2015 at 23:19 Comment(7)
Actually the solution I added above did the trick, but thank you for help anyway. I'm curious so I will give it a try :)Disillusionize
Setting onInterceptTouchEvent to the coordinator might give you some problem in the future. This is the "official" solution (if I got your question).Smallsword
Can't make it work with this solution. Can you explain a little bit more, please? ThanksWicks
@joaquin if canDrag returns true, you can scroll the whole view by scrolling the appbarlayout. If canDrag returns false, the appbarlayout does not react to scroll events.Smallsword
The "behavior" variable that is returned to me is null. How did you get it to work?Tomaso
i got null while accessing params.getBehavior. This answer (https://mcmap.net/q/50260/-using-appbarlayout-behavior-dragcallback-to-control-scroll-of-collapsing-toolbar-layout) is another way to change behavior and it worked for me:Jola
don't forget about the ''Note"Firedamp
L
40

Problem

  1. AppBarLayout scrolls even if the scroll content fits the screen.
  2. It is because by default we can drag AppBarLayout by touching & dragging AppBarLayout.

Solution

  1. We will disable "Dragging" behaviour for AppBarLayout.

    // Disable "Drag" for AppBarLayout (i.e. User can't scroll appBarLayout by directly touching appBarLayout - User can only scroll appBarLayout by only using scrollContent)
    if (appBarLayout.getLayoutParams() != null) {
        CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
        AppBarLayout.Behavior appBarLayoutBehaviour = new AppBarLayout.Behavior();
        appBarLayoutBehaviour.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
            @Override
            public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
                return false;
            }
        });
        layoutParams.setBehavior(appBarLayoutBehaviour);
    }
    

Reference

  1. This is just extension of "natario's" accepted answer above.

  2. https://developer.android.com/reference/android/support/design/widget/AppBarLayout.Behavior.DragCallback.html

Litman answered 26/10, 2016 at 16:12 Comment(1)
Hi Vasanth! I want to disable user scroll (of CoordinatorLayout) when he scrolls into the recyclerview. how can I do that please?Brookweed
W
31

You can accomplish this by defining a custom app:layout_behavior in xml. With this approach you don't have to worry about getting a reference to the LayoutParams and doing null checks.

  <android.support.design.widget.AppBarLayout
      android:id="@+id/app_bar_layout"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:layout_behavior="com.yourcompany.FixedAppBarLayoutBehavior"
      >

Then create a custom class that extends from AppBarLayout.Behavior.

public class FixedAppBarLayoutBehavior extends AppBarLayout.Behavior {

  public FixedAppBarLayoutBehavior(Context context, AttributeSet attrs) {
    super(context, attrs);

    setDragCallback(new DragCallback() {
      @Override public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
        return false;
      }
    });
  }
}

Updated with Kotlin version:

class FixedAppBarLayoutBehavior(context: Context, attrs: AttributeSet) : AppBarLayout.Behavior(context, attrs) {
  init {
    setDragCallback(object : DragCallback() {
      override fun canDrag(appBarLayout: AppBarLayout): Boolean = false
    })
  }
}
Wrecker answered 8/9, 2017 at 15:48 Comment(0)
D
6

So after two hours of trying I have found a solution, which is pretty simple. I just needed to extend CoordinatorLayout and override OnInterceptTouchEvent method so the class looks like this:

public class NonTouchableCoordinatorLayout extends CoordinatorLayout {
public NonTouchableCoordinatorLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return false;
}

}

Disillusionize answered 5/12, 2015 at 23:7 Comment(0)
S
1

you can use the NestedScrollView.setNestedScrollingEnabled(false) to disable the AppBarLayout nestScroll envent

Shahaptian answered 24/10, 2017 at 2:10 Comment(1)
you can still scroll/expand appbar by dragging your finger on the appbar area.Shikari

© 2022 - 2024 — McMap. All rights reserved.