How to disable scrolling of AppBarLayout in CoordinatorLayout?

前端 未结 5 1763
挽巷
挽巷 2020-12-02 23:34

I have MapFragment with parallax effect inside AppBarLayout:

I want to disable scrolling on AppBarLayout, because it

相关标签:
5条回答
  • 2020-12-02 23:38

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

    0 讨论(0)
  • 2020-12-02 23:41

    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

    0 讨论(0)
  • 2020-12-02 23:47

    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
        })
      }
    }
    
    0 讨论(0)
  • 2020-12-02 23:59

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

    }

    0 讨论(0)
  • 2020-12-03 00:04

    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.

    0 讨论(0)
提交回复
热议问题