Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable vertical scroll in CollapsingToolbarLayout / AppBarLayout

I would like the vertical scroll on the CollapsingToolbarLayout / AppBarLayout ONLY when the scroll/touch event occurs in the nestedscrollview (this is working), but if the user tries to scroll the CollapsingToolbarLayout / AppBarLayout directly it should not work. I need this because the scroll/touch events there are messing with my recyclerview scroll events.

I have this structure:

CoordinatorLayout

-- AppBarLayout

---- CollapsingToolbarLayout (scrollflags: scroll, exitUntilCollapsed, snap)

------ Toolbar (CollapseMode: pin)

------ RecyclerView (Horizontal, CollapseMode: pin)

----- /CollapsingToolbarLayout

-- /AppBarLayout

-- NestedScrollView (Behaviour: appbar_scrolling_view_behavior)

-- /NestedScrollView

/ CoordinatorLayout

I tried overriding onTouch() and onInterceptTouchEvent() for both CollapsingToolbarLayout / AppBarLayout but it keeps intercepting the touch event/scroll.

like image 860
nsL Avatar asked Nov 22 '16 19:11

nsL


People also ask

How to bind a scrolling view to an appbarlayout?

AppBarLayout also requires a separate scrolling sibling in order to know when to scroll. The binding is done through the AppBarLayout.ScrollingViewBehavior behavior class, meaning that you should set your scrolling view's behavior to be an instance of AppBarLayout.ScrollingViewBehavior.

What is collapsingtoolbarlayout?

CollapsingToolbarLayout is a wrapper for Toolbar which implements a collapsing app bar. It is designed to be used as a direct child of a AppBarLayout. CollapsingToolbarLayout contains the following features:

How to hide the vertical scrollbar in a page?

To only hide the vertical scrollbar, or only the horizontal scrollbar, use overflow-y or overflow-x: Note that overflow: hidden will also remove the functionality of the scrollbar. It is not possible to scroll inside the page. Tip: To learn more about the overflow property, go to our CSS Overflow Tutorial or CSS overflow Property Reference.

How to scroll off-screen with appbar?

Once content starts scrolling, the app bar will scroll faster than the content until it gets out of the overlapping content view. Once the content reaches top, app bar comes upside of the content and content goes underneath and scrolls smoothly. The whole AppBar can scroll off-screen along with content and can be returned while reverse scrolling.


Video Answer


2 Answers

I wrote a BindingAdapter for nsL's answer:

@BindingAdapter("scrollable")
fun setScrollable(appBarLayout: AppBarLayout, scrollable: Boolean) {
    val layoutParams = appBarLayout.layoutParams as CoordinatorLayout.LayoutParams
    val behavior = (layoutParams.behavior as? AppBarLayout.Behavior) ?: AppBarLayout.Behavior()
    behavior.setDragCallback(object : AppBarLayout.Behavior.DragCallback() {
        override fun canDrag(appBarLayout: AppBarLayout): Boolean = scrollable
    })
    layoutParams.behavior = behavior
}

You can use it in a databinding layout like this:

<com.google.android.material.appbar.AppBarLayout
    ...
    app:scrollable="@{true/false}"
    ... >
...
</com.google.android.material.appbar.AppBarLayout>

In my case I also wanted to disable the scroll on the NestedScrollView, which is why I wrote a second BindingAdapter:

@BindingAdapter("scrollable")
fun setScrollable(nestedScrollView: NestedScrollView, scrollable: Boolean) {
    nestedScrollView.setOnTouchListener { _, _ -> !scrollable }
}
like image 187
janosch Avatar answered Sep 21 '22 15:09

janosch


Ok, i found out the solution for this.

You just have to override the onDrag() method in the AppBarLayout behaviour and the scroll wont be triggered if the touch occurs on top of the AppBarLayout view.

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

Solution from here: How to disable scrolling of AppBarLayout in CoordinatorLayout?

If you run into NullPointerException because of a null Behavior, you should assign one first:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppbar.getLayoutParams();
params.setBehavior(new AppBarLayout.Behavior());
like image 27
nsL Avatar answered Sep 20 '22 15:09

nsL