How to disable scrolling of AppBarLayout in CoordinatorLayout?
Solution 1
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.
Solution 2
Problem
- AppBarLayout scrolls even if the scroll content fits the screen.
- It is because by default we can drag AppBarLayout by touching & dragging AppBarLayout.
Solution
-
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
This is just extension of "natario's" accepted answer above.
Solution 3
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
})
}
}
Solution 4
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;
}
}
Solution 5
you can use the NestedScrollView.setNestedScrollingEnabled(false)
to disable the AppBarLayout nestScroll envent
janox1x2x3
Updated on October 22, 2020Comments
-
janox1x2x3 over 3 years
I have
MapFragment
with parallax effect insideAppBarLayout
: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 ofAppBarLayout
by scrollingRecyclerView
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.