Utilisation de BottomSheetBehavior avec un CoordinatorLayout interne

La bibliothèque de support de conception v. 23.2 introduit BottomSheetBehavior , qui permet aux enfants d'un coordinateur d'agir comme des feuilles inférieures (les vues peuvent être déplacées depuis le bas de l'écran).

Ce que j'aimerais faire, c'est d'avoir, en vue de la feuille inférieure , la vue suivante (le coordinateur typique + collapsing stuff):

  • Comment afficher un bouton à la fin d'une Android ListView
  • Le serveur ADB n'a pas ACK sur MacOS
  • Android obtient tous les contacts numéro de téléphone dans ArrayList
  • Android - Comment faire pour que ce dialogue d'alerte puisse être défilé?
  • Réglage de la taille d'une seule rangée dans StaggeredGridLayoutManager
  • Fonction étrange dans ActivityManager: isUserAMonkey. Qu'est-ce que cela signifie, à quoi sert-il?
  •  <CoordinatorLayout app:layout_behavior=“@string/bottom_sheet_behavior”> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> <NestedScrollView> <LinearLayout> < Content ... /> </LinearLayout> </NestedScrollView> </CoordinatorLayout> 

    Malheureusement, les vues en bas de la feuille devraient implémenter un défilement imbriqué, ou ils n'obtiendront pas d'événements de défilement. Si vous essayez avec une activité principale, puis chargez cette vue en tant que feuille inférieure, vous verrez que les événements de défilement n'agissent que sur la «feuille» de papier, avec un comportement étrange, comme vous pouvez le constater si vous continuez à lire.

    Je suis certain que cela peut être traité en sous- BottomSheetBehavior CoordinatorLayout , ou encore mieux en sous- BottomSheetBehavior . Avez-vous un indice?

    Quelques idées

    • requestDisallowInterceptTouchEvent() devrait être utilisé, pour voler les événements du parent dans certaines conditions:

      • Lorsque le décalage AppBarLayout est> 0
      • Lorsque le décalage AppBarLayout est == 0, mais nous AppBarLayout (pensez-y pour une seconde et vous verrez)
    • La première condition peut être obtenue en définissant un OnOffsetChanged dans la barre interne de l'application;

    • La seconde nécessite une gestion de l'événement, par exemple:

       switch (MotionEventCompat.getActionMasked(event)) { case MotionEvent.ACTION_DOWN: startY = event.getY(); lastY = startY; userIsScrollingUp = false; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: userIsScrollingUp = false; break; case MotionEvent.ACTION_MOVE: lastY = event.getY(); float yDeltaTotal = startY - lastY; if (yDeltaTotal > touchSlop) { // Moving the finger up. userIsScrollingUp = true; } break; } 

    Problèmes

    Inutile de dire que je ne peux pas faire ce travail en ce moment. Je ne peux pas attraper les événements lorsque les conditions sont remplies et ne pas les attraper dans d'autres cas. Dans l'image ci-dessous, vous pouvez voir ce qui se passe avec un CoordinatorLayout standard:

    • La feuille est rejetée si vous faites défiler vers le bas sur la barre d'application, mais pas si vous faites défiler vers le bas sur le contenu imbriqué. Il semble que les événements de défilement imbriqués ne se propagent pas au comportement du Coordinateur;

    • Il existe également un problème avec l'appbar interne: le contenu de défilement imbriqué ne suit pas l'appbar lorsqu'il est effondré.

    Entrez la description de l'image ici

    J'ai configuré un exemple de projet sur github qui montre ces problèmes.

    Juste pour être clair, le comportement désiré est:

    • Comportement correct des vues des appbars / défilements à l'intérieur de la feuille;

    • Lorsque la feuille est agrandie, elle peut s'effondrer en mode défilement vers le bas, mais uniquement si l'appbar interne est entièrement agrandie . À l'heure actuelle, il s'effondre sans tenir compte de l'état de l'application et uniquement si vous faites glisser l'appbar;

    • Lorsque la feuille est effondrée, les gestes vers le haut vont l'étendre (sans effet sur l'appbar interne).

    Un exemple de l'application de contacts (qui n'utilise probablement pas BottomSheetBehavior, mais c'est ce que je veux):

    Entrez la description de l'image ici

  • Custom android.app.Application not firing onCreate event
  • Chaîne json de format Android dans la sortie LogBB AdB
  • Comment créer une requête PUT dans la bibliothèque ION
  • Quelle est la différence entre DVM et JVM?
  • Android: la notification cesse de mettre à jour une fois qu'il a été mis à jour pour un certain nombre de fois sur Kit-Kat
  • AndroidAnnotations ne peut pas trouver la classe de symboles
  • 6 Solutions collect form web for “Utilisation de BottomSheetBehavior avec un CoordinatorLayout interne”

    Je viens juste de suivre la façon dont vous avez posé la question ci-dessus et de trouver une solution qui pourrait nécessiter plus d'explications. Veuillez suivre votre exemple de code et intégrer la partie supplémentaire dans votre xml pour que cela se comporte comme un comportement BottomSheeet

     <CoordinatorLayout> <AppBarLayout> <Toolbar app:layout_collapseMode="pin"> </Toolbar> </AppBarLayout> <NestedScrollView app:layout_behavior=“@string/bottom_sheet_behavior” > <include layout="@layout/items" /> </NestedScrollView> <!-- Bottom Sheet --> <BottomSheetCoordinatorLayout> <AppBarLayout <CollapsingToolbarLayout"> <ImageView /> <Toolbar /> </CollapsingToolbarLayout> </AppBarLayout> <NestedScrollView"> <include layout="@layout/items" /> </NestedScrollView> </BottomSheetCoordinatorLayout> </CoordinatorLayout> 

    Remarque: La solution qui m'a fonctionné m'a déjà expliqué dans le dernier commentaire de votre question

    Meilleure explication: https://github.com/laenger/BottomSheetCoordinatorLayout

    J'ai finalement publié ma mise en œuvre. Trouvez-le sur Github ou directement auprès de jcenter:

     compile 'com.otaliastudios:bottomsheetcoordinatorlayout:1.0.0' 

    Tout ce que vous devez faire est d'utiliser BottomSheetCoordinatorLayout comme vue racine pour votre feuille inférieure. Il gonflera automatiquement un comportement de travail pour lui-même, alors ne vous inquiétez pas.

    Je l'ai utilisé depuis longtemps et ne devrait pas avoir de problèmes de défilement, supporte le renversement de l'ABL, etc.

    Si le premier enfant est nestedscroll cela se produira d'autres problèmes. Cette solution est réglée sur mon problème, j'espère également réparer le vôtre.

     <CoordinatorLayout app:layout_behavior=“@string/bottom_sheet_behavior”> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> </LinearLayout> <NestedScrollView> <LinearLayout> < Content ... /> </LinearLayout> </NestedScrollView> </LinearLayout> </CoordinatorLayout> 

    Essayez de ne pas utiliser NestedScrollView avec LinearLayout , cela cause également des problèmes dans mon application. Il suffit d'utiliser uniquement LinearLayout , fonctionne bien pour moi.

    Essayez ce qui suit:

     <CoordinatorLayout app:layout_behavior=“@string/bottom_sheet_behavior”> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> <LinearLayout> <!--don't forget to addd this line--> app:layout_behavior="@string/appbar_scrolling_view_behavior"> < Content ... /> </LinearLayout> 

    J'ai suivi le projet de test initial de GingerLenger à propos de ce problème, et je suis heureux de vous faire une solution pour certains de ses problèmes, car j'ai également eu ce problème dans mon application.

    C'est une solution à son problème: ❌ la barre d'outils s'effondre trop tôt

    Pour éviter cela, vous devez créer votre AppBarLayout.Behavior personnalisé, car c'est quand vous faites défiler vers le haut tout en faisant glisser que AppBarLayout.behavior obtient le mouvement de défilement. Nous devons détecter si c'est dans STATE_DRAGGING et revenir simplement pour éviter de cacher ou d'effondrer la barre d'outils prématurément.

     public class CustomAppBarLayoutBehavior extends AppBarLayout.Behavior { private CoordinatorLayoutBottomSheetBehavior behavior; public CustomAppBarLayoutBehavior() { } public CustomAppBarLayoutBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) { behavior = CoordinatorLayoutBottomSheetBehavior.from(parent); return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes); } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) { if(behavior.getState() == CoordinatorLayoutBottomSheetBehavior.STATE_DRAGGING){ return; }else { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); } } @Override public void setDragCallback(@Nullable DragCallback callback) { super.setDragCallback(callback); } } 

    Ce peut être un bon début sur la façon dont nous résolvons les autres problèmes:

    La barre d'outils can ne peut pas être effondrée par des traînées

    ❌ la disposition du coordinateur principal consomme du scroll

    Je ne suis pas vraiment une bonne personne d'interface utilisateur / animation, mais le travail acharné comprend la compréhension du code parfois, la recherche de la bonne fonction de rappel / remplacement pour la mise en œuvre.

    Définissez ceci comme un comportement à appbarlayout

     <android.support.design.widget.AppBarLayout android:id="@+id/bottom_sheet_appbar" style="@style/BottomSheetAppBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="your.package.CustomAppBarLayoutBehavior"> 

    La disposition pour l'écran complet de la mise en page de l'appbar est la suivante:

     <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="@dimen/detail_backdrop_height" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:fitsSystemWindows="true"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginStart="48dp" app:expandedTitleMarginEnd="64dp"> <ImageView android:id="@+id/backdrop" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:fitsSystemWindows="true" app:layout_collapseMode="parallax" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingTop="24dp"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/card_margin"> <LinearLayout style="@style/Widget.CardContent" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Info" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/card_margin" android:layout_marginLeft="@dimen/card_margin" android:layout_marginRight="@dimen/card_margin"> <LinearLayout style="@style/Widget.CardContent" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Friends" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/card_margin" android:layout_marginLeft="@dimen/card_margin" android:layout_marginRight="@dimen/card_margin"> <LinearLayout style="@style/Widget.CardContent" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Related" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> </LinearLayout> </android.support.v4.widget.NestedScrollView> <android.support.design.widget.FloatingActionButton android:layout_height="wrap_content" android:layout_width="wrap_content" app:layout_anchor="@id/appbar" app:layout_anchorGravity="bottom|right|end" android:src="@drawable/ic_discuss" android:layout_margin="@dimen/fab_margin" android:clickable="true"/> 

    Et ensuite, vous devez implémenter AppBarLayout.OnOffsetChangedListener dans votre classe et définir le décalage de l'écran.

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.