Using the BottomSheetBehavior Method with an Internal Layout Coordinator

Design Support Library v. 23.2 v. 23.2 introduces the BottomSheetBehavior , which allows the coordinator children to act as bottom sheets (views are dragged from the bottom of the screen).

The identifier should have, as a representation of the bottom sheet , the following representation (typical coordinator + folding material):

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

Unfortunately, the views of the bottom sheet must implement nested scrolling, otherwise they will not receive scroll events. If you try to perform the main action, and then load this view as the bottom sheet, you will see that the scroll events only act on the “sheet” of paper with some strange behavior, as you can see if you continue to read.

I am sure that this can be handled by subclassing the CoordinatorLayout or even better by subclassing the BottomSheetBehavior . Do you have a hint?

Some thoughts

  • requestDisallowInterceptTouchEvent() should be used to steal events from the parent in some conditions:

    • when the offset AppBarLayout > 0
    • when the AppBarLayout offset is == 0, but we scroll (think about it for a second and look at you)
  • the first condition can be obtained by setting OnOffsetChanged to the internal application panel;

  • the second requires some event handling, for example:

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

Questions

Needless to say, I can't do this job right now. I can not catch events when the conditions are met, and do not catch them in other cases. In the image below you can see what happens with the standard Layout coordinator:

  • The sheet is rejected if you scroll through the application panel but do not scroll down the attached content. It seems that nested scroll events do not apply to the Coordinator’s behavior,

  • There is also a problem with the application’s internal panel: the nested scroll content does not follow the application panel when it is reset.

enter image description here

I installed a sample project on github that shows these issues.

To be clear, the desired behavior:

  • Correct behavior of application types / scrolling inside the sheet;

  • When a sheet expands, it can curl down to scroll, but only if the application’s inner panel is fully expanded. . Now it crashes without taking into account the state of the application panel, and only if you drag the application panel,

  • When a sheet is minimized, scrolling gestures will expand it (without affecting the internal application panel).

An example from the contacts application (which probably does not use the BottomSheetBehavior method, but this is what I want):

enter image description here

+50
android ontouchlistener android-support-library ontouchevent android-support-design
Mar 25 '16 at 23:50
source share
6 answers

I finally released my implementation. Search on Github or directly from jcenter:

 compile 'com.otaliastudios:bottomsheetcoordinatorlayout:1.0.0' 

All you have to do is use the BottomSheetCoordinatorLayout as the root view for your bottom sheet. It will automatically inflate working behavior for itself, so don't worry about it.

I have been using this for a long time and should not have scrolling issues, supports drag and drop to ABL, etc.

+2
Apr 20 '17 at 19:34 on
source share

I just went on how you asked the above question, and come up with a solution that may require more explanation. Please follow your sample code and integrate the extra part into your xml to make it behave like BottomSheeet behavior.

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

Note. The solution that worked for me is already explained in the last comment on your question

Best explanation: https://github.com/laenger/BottomSheetCoordinatorLayout

+1
Jan 11 '17 at 7:50
source share

If the first child is nestedscroll , this will cause some other problems. This solution is fixed by my problem, I hope also fix yours.

 <CoordinatorLayout app:layout_behavior="@string/bottom_sheet_behavior"> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> </LinearLayout> <NestedScrollView> <LinearLayout> < Content ... /> </LinearLayout> </NestedScrollView> </LinearLayout> </CoordinatorLayout> 
0
Dec 02 '16 at 8:57
source share

Try not to use NestedScrollView with LinearLayout , this also causes problems in my application. Just use only LinearLayout instead, works great for me.

Try the following:

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

0
Jan 01 '16 at 17:46 on
source share

I have been following the jiant initial github test project project on this issue, and I am happy to share with you a solution for some of its problems, since I also needed this behavior in my application.

this is the solution to his problem: ❌ the toolbar sometimes crashes too soon

to prevent this, you need to create your own custom AppBarLayout.Behavior , since this is when you scroll up while still dragging that AppBarLayout.Behavior gets the scroll motion. We need to determine if it is in STATE_DRAGGING and just go back to prematurely hide / collapse the toolbar.

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

this may be a good start to how we solve other problems:

❌ toolbar cannot be demolished by dragging and dropping

❌ location of the main coordinator consumes several scrolls

I'm actually not a good user interface / animation, but hard work pays off, sometimes understanding the code, finding the right callback / override function.

set this as behavior for 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"> 
0
Mar 14 '17 at 3:28
source share

The layout for the full screen layout of the application bar is as follows: -

 <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"/> 

after which you should implement AppBarLayout.OnOffsetChangedListener in your class and set the screen offset.

-3
Apr 02 '16 at 5:59
source share



All Articles