web-dev-qa-db-fra.com

Désactiver le défilement vertical dans CollapsingToolbarLayout/AppBarLayout

Je voudrais le défilement vertical sur CollapsingToolbarLayout/AppBarLayout UNIQUEMENT lorsque l'événement scroll/touch se produit dans le nestedscrollview (cela fonctionne), mais si l'utilisateur essaie de faire défiler le CollapsingToolbarLayout/AppBarLayout directement, cela ne devrait pas fonctionner. J'ai besoin de cela parce que les événements de défilement/touch touchent mes événements de défilement Recyclage.

J'ai cette 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

J'ai essayé de surcharger onTouch () et onInterceptTouchEvent () à la fois pour CollapsingToolbarLayout/AppBarLayout mais l'interception de l'événement tactile/défilement continue.

10
nsL

Ok, j'ai trouvé la solution pour ça.

Il vous suffit de remplacer la méthode onDrag () dans le comportement AppBarLayout et le défilement ne sera pas déclenché si le contact se produit au-dessus de la vue AppBarLayout.

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 d'ici: Comment désactiver le défilement de AppBarLayout dans CoordinatorLayout?

Si vous rencontrez NullPointerException à cause d'un comportement null, vous devez d'abord en affecter un:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppbar.getLayoutParams();
params.setBehavior(new AppBarLayout.Behavior());
24
nsL

J'ai écrit un BindingAdapter pour la réponse de nsL:

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

Vous pouvez l'utiliser dans une mise en page de liaison de données comme ceci:

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

Dans mon cas, je voulais aussi désactiver le défilement sur le NestedScrollView, c'est pourquoi j'ai écrit un deuxième BindingAdapter: 

@BindingAdapter("scrollable")
fun setScrollable(nestedScrollView: NestedScrollView, scrollable: Boolean) {
    nestedScrollView.setOnTouchListener { _, _ -> !scrollable }
}
0
Janosch Pelzer