I have MapFragment
with parallax effect inside AppBarLayout
:
I want to disable scrolling on AppBarLayout
, because it
you can use the NestedScrollView.setNestedScrollingEnabled(false)
to disable the AppBarLayout nestScroll envent
Problem
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.
https://developer.android.com/reference/android/support/design/widget/AppBarLayout.Behavior.DragCallback.html
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
})
}
}
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;
}
}
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.