How to disable scrolling of AppBarLayout in CoordinatorLayout?

心已入冬 提交于 2019-11-27 12:25:06

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.

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

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

}

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!