J'ai MapFragment
avec effet de parallaxe à l'intérieur de AppBarLayout
:
Je souhaite désactiver le défilement sur AppBarLayout
, car il n'est pas possible de se déplacer sur la carte, car les événements tactiles sur la carte sont toujours traités comme des événements de défilement. Je voudrais gérer la réduction de AppBarLayout
en faisant défiler uniquement RecyclerView
, qui se trouve en bas de l'écran.
C'est mon xml:
<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.AppBarLayout
Android:id="@+id/appbar"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<Android.support.design.widget.CollapsingToolbarLayout
Android:id="@+id/collapsing_toolbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:fitsSystemWindows="true"
app:contentScrim="@color/white"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:titleEnabled="false">
<FrameLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
app:layout_collapseMode="parallax"
Android:fitsSystemWindows="true">
<fragment
Android:id="@+id/map"
Android:name="com.androidmapsextensions.SupportMapFragment"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</FrameLayout>
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="73dp"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<include
Android:id="@+id/search_bar"
layout="@layout/layout_searchbar" />
</Android.support.v7.widget.Toolbar>
<View
Android:id="@+id/toolbar_shadow"
Android:layout_width="match_parent"
Android:layout_height="3dp"
Android:layout_below="@id/search_bar"
Android:layout_gravity="bottom"
Android:background="@drawable/toolbar_dropshadow"
Android:visibility="gone" />
</Android.support.design.widget.CollapsingToolbarLayout>
</Android.support.design.widget.AppBarLayout>
<RecyclerView
Android:id="@+id/farm_list"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@Android:color/transparent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
Merci pour votre réponse.
Je ne suis pas sûr de l'avoir, mais je pense que vous cherchez un DragCallback
.
L’interface DragCallback
permet de choisir si la vue de défilement parentale doit être contrôlée par des défilements sur la AppBarLayout
.
Vous pouvez en définir un en appelant:
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;
}
});
En retournant toujours false
, votre vue de défilement ne sera plus contrôlée par ABL.
Note: avant d'appeler ceci, vous devriez vérifier que ViewCompat.isLaidOut(appBarLayout)
, sinon params.getBehavior()
retournera null.
Problème
Solution
Nous allons désactiver le comportement "Dragging" pour 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);
}
Référence
Ceci est juste une extension de la réponse acceptée de "natario" ci-dessus.
Vous pouvez accomplir cela en définissant un app:layout_behavior
personnalisé en xml. Avec cette approche, vous n'avez pas à vous soucier d'obtenir une référence à LayoutParams
et d'effectuer des contrôles nuls.
<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"
>
Créez ensuite une classe personnalisée qui s'étend de 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;
}
});
}
}
Mise à jour avec la version Kotlin:
class FixedAppBarLayoutBehavior(context: Context, attrs: AttributeSet) : AppBarLayout.Behavior(context, attrs) {
init {
setDragCallback(object : DragCallback() {
override fun canDrag(appBarLayout: AppBarLayout): Boolean = false
})
}
}
Donc, après deux heures d’essais, j’ai trouvé une solution assez simple. J'avais juste besoin d'étendre la variable CoordinatorLayout
et de remplacer la méthode OnInterceptTouchEvent
pour que la classe ressemble à ceci:
public class NonTouchableCoordinatorLayout extends CoordinatorLayout {
public NonTouchableCoordinatorLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
}
vous pouvez utiliser la NestedScrollView.setNestedScrollingEnabled(false)
pour désactiver l'événement Scroll suivant de AppBarLayout