Sliding up image with Official Support Library 23.x.+ bottomSheet like google maps –

Development issue/problem:

I want to get the same behaviour as Google Maps with 23.x.+ library support and without any 3rd library.

NOTE: This isn’t a double question, because:

I already have the official background page running (even in the tab and view the beeper).

What’s driving me crazy is how do I control the behavior of the image that appears at the bottom of the page when you push it up, with the official BottomSheet?
I tried to use an anchor like the FAB without success.
I’ve read something about using a scroller, but people say it’s not as smooth and fast as Google Maps.

My XML (I don’t think it helps, but it doesn’t matter) :

How can I solve this problem?

Solution 1:

If you want to get it with the 23.4.0.+ support library, I’ll tell you how I got it and how it works.

From what I can see, the activity/fragment has the following behavior:

  1. 2 animated toolbars that react to the movements of the bottom plate.
  2. FAB that is hidden if it is next to the modal toolbar. (The one that appears when you drag it up).
  3. The background image behind the bottom sheet has a kind of parallax effect.
  4. Title (TextView) in the toolbar that appears when the bottom sheet is reached.
  5. The notification status bar can make the background transparent or colored.
  6. Adjustable behaviour of the base plate with anchor status.

Note 2 : This answer says 6 things, not 1 or 2 like the other question, do you see the difference now?

Well, let’s start by checking one:

When you open this view in google maps, you can see the toolbar where you can search. It’s the one thing I don’t do as google maps because I wanted to make it more general. Anyway, the toolbar is located in the AppBarLayout and is hidden when you start dragging the bottom sheet, and it will reappear when the bottom sheet reaches COLLAPSED state.
To do this, you have to:

  • Create a behavior and extend it from AppBarLayout.ScrollingViewBehavior
  • Replaces the layoutDependsOn and onDependentViewChanged methods. This is how you hear the movements of the lower blade.
  • Create methods to show and hide AppBarLayout/Toolbar with animation.

This is how I did it for the first toolbar or ActionBar :

PublicBooleanDependsOn(CoordinatorLayout parent, View child, View dependency) {returns an instance of NestedScrollView dependency;}.

Public Boolean
onDependentViewChanged (CoordinatorLayout parent, View child,
View dependency) {

if (mKind ==zero) {
initial values (child, dependency);
returns false;

float dVerticalScroll = dependency.getY() – mPreviousY ;
mPreviousY = dependency.getY() ;

if (dVerticalScroll)

the complete file if you need it

Second toolbar or modal toolbar :
You have to undo the same methods, but in this case you are dealing with more behavior:

  • Show/hide animation toolbar
  • Changing the color/background of the status bar
  • Show/hide the BottomSheet header in the toolbar
  • Close the base plate or put it in the folded position.

The code for that is a bit long, so I’m leaving the link


This is also an adapted behavior, but it comes from the FloatingActionButton.Behavior. In onDependentViewChanged you need to check when it reaches offSet or the point where you want to hide it. In my case, I want to hide it if it is near the second toolbar, so I search the parent FAB (CoordiantorLayout) for an AppBarLayout that contains a toolbar, and then use the position of the toolbar as OffSet :

Public Boolean definition
onDependentViewChanged (CoordinatorLayout parent, FloatingActionButton child, View dependence) {

if (offset == 0)
setOffsetValue(parent) ;

if (dependency.getY() offset && child.getVisibility() != View.VISIBLE)

reversing false;

Full reference to user-defined FOB behaviour

The image behind the base plate with the parallax effect:
Like others, the custom behavior, the only tricky point is the small algorithm that keeps the image linked to BottomSheet and avoids crashing the image as a parallax effect by default:

Public Boolean
onDependentViewChanged (CoordinatorLayout parent, View child,
View dependency) {

if (mYmultiplicator == 0) {
initial values (child, dependency);
return true;

float dVerticalScroll = dependency.getY() – mPreviousY ;
mPreviousY = dependency.getY() ;

// output
if (dVerticalScroll = 0 && dependence.getY())

full background image file with parallax effect

Let’s go to the end: Custom BottomSheetBehavior
To perform the 3 steps, you first have to underestimate that BottomSheetBehavior has 5 states by default: STATE_DRAGGING, STATE_SETTLING, STATE_EXPANDED, STATE_COLLAPSED, STATE_HIDDEN and for Google Maps behavior, the intermediate state between collapsed and extended must be added : STATE_ANCHOR_POINT.
I tried unsuccessfully to extend the standard BottomSheetBehavior, so I will just copy all the code and change what I need.
To realize what I’m talking about, follow these steps:

  1. Create a Java class and expand it from CoordinatorLayout.Behavior.
  2. Copy the insertion code from the standard BottomSheetBehavior file to a new file.
  3. Change the vertical square brackets with the following code:

public int clampViewPositionVertical(View child, int top, int dy) {
return constrain(top, mMinOffset, mHideable? mParentHeight: mMaxOffset);
int constrain(int amount, int low, int high) {
return amount < low? low: (amount > high? high: amount);

  1. Add a new state

public static end result int STATE_ANCHOR_POINT = X ;

  1. Change the following methods: onLayoutChild, onStopNestedScroll, BottomSheetBehavior of(V view), and setState (optional).

public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) {
// The parent was first set
as (mState != STATE_DRAGGING && mState != STATE_SETTLING) {
as (ViewCompatible.getFitsSystemWindows(parent) &&
! ViewCompatible.getFitsSystemWindows(child)) {
ViewCompat.setFitsSystemWindows(child, true);
parent.onLayoutChild(child, layoutDirection);
// Lower sheet offset
mParentHeight = parent.getHeight();
mMinOffset = Math.max(0, mParentHeight – child.getHeight());
mMaxOffset = Math.max(mParentHeight – mPeekHeight, mMinOffset)

//if (mState == STATE_EXPANDED) {// ViewCompatible.offsetTopAndBottom(child, mMinOffset);//} other than (mHideable && mState == STATE_HIDDEN… if (mState == STATE_ANCHOR_POINT) {ViewCompat.offsetTopAndBottom(child, mAnchorPoint);} else if (mState == STATE_EXPANDED) {ViewCompat.offsetTopAndBottom(child, mMinOffset);} different if (mHideable && mState == STATE_HIDDEN) {ViewCompat.offsetTopAndBottom(child, mParentHeight);} other if (mState == STATE_COLLAPSED) {ViewCompat.offsetTopAndBottom(child, mMaxOffset);}as (mViewDragHelper == null) {mViewDragHelper = ViewDragHelper.create(parent, mDragCallback);}mViewRef = new WeakReference(child);mNestedScrollingChildRef = new WeakReference(findScrollingChild(child));returns where;}.

public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {
if (child.getTop() == mMinOffset) {
if (target != mNestedScrollingChildRef.get() | !mNestedScrolled) {
int top;
int targetState;
if (mLastNestedScrollDy > 0) {
//top = mMinOffset;
//targetState = STATE_EXPANDED;
int currentTop = child.getTop();
if (currentTop > mAnchorPoint) {
top = mAnchorPoint;
different {
top = mMinOffset;
targetState = STATE_EXPANDED ;
} different if (mHideable & shouldHide(child, getYVelocity()) {
top = mParentHeight;
targetState = STATE_HIDDEN;
} else if (mLastNestedScrollDy == 0) {
int currentTop = child.getTop();
if (Math.abs(currentTop – mMinOffset) mAnchorPoint) {
top = mMaxOffset;
targetState = STATE_COLLAPSED;
else {
top = mAnchorPoint;
if (mViewDragHelper.smoothSlideViewTo(child, child.getLeft(, above)) {
ViewCompatible.postOnAnimation(child, new SettleRunnable(child, targetState)));
} otherwise {
mNestedScrolled = false;

public last empty setState(@State int state) {
if (state == mState) {
if (mViewRef == null) {
// View not yet posted; change mState and let onLayoutChild handle it later
* New behaviour (added : state == STATE_ANCHOR_POINT ||)
if (state == STATE_COLLAPSED || State == STATE_EXPANDED |
(mHideable && state == STATE_HIDDEN)) {
mState = state;
V child = mViewRef.get();
if (child == null) {
int top;
if (state == STATE_COLLAPSED) {
top = mMaxOffset;
} else if (state == STATE_ANCHOR_POINT) {
top = mAnchorPoint ;
} else if (state == STATE_EXPANDED) {
top = mMinOffset ;
} else if (mHideable && state == STATE_HIDDEN) {
top = mParentHeight ;
} else {
throw new IllegalArgumentException(argument about illegal state : +state);
as (mViewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) {
ViewCompat.postOnAnimation(child, new SettleRunnable(child, state));

public static BottomSheetBehaviorGoogleMapsLike from(V view) {
ViewGroup.LayoutParams params = view.getLayoutParams();
as (!(params instanceof CoordinatorLayout.LayoutParams)))
new IllegalArgumentException(view is not a child of CoordinatorLayout);
CoordinatorLayoutParams behavior = (!(CoordinatorLayout).LayoutParams) params)
as (!!(instanceof BottomSheetBehaviorGoogleMapsLike)) {
throw new IllegalArgumentException(
The display is not associated with BottomSheetBehaviorGoogleMapsLike) behaviour;
return (BottomSheetBehaviorGoogleMapsLike) behaviour;

Link to the whole project where you can see all custom behaviors

Note3 : Next time, add a comment with the question to change the answer, or ask why this answer is more similar than my other answers on the same topic BEFORE closing it or marking it as a duplicate.

And here’s the deal:
[ ]

Solution 2:

You can achieve this effect by using the coordinated layout behaviour. You will need to expand the CoordinatorLayout.Behaviour classroom and write a dependency on one of the positions in the Coordinator layout, keeping your image with the view as a child…. For simplicity, you should link the custom writing behavior to the image contained in the display. For help with writing, see
Writing Behaviour.

Good luck!

Related Tags:

collapsing toolbar android github,coordinatorlayout behavior,appbarlayout,coordinatorlayout androidx dependency,coordinatorlayout anchor,recyclerview inside bottomsheet not scrolling, androidx,com android support appcompat-v7:23.4 0,android_support_version 28, not found,com android support appcompat release notes,collapsingtoolbarlayout without toolbar,collapsing toolbar'' android design support library,collapsing toolbar scrollview,sliding toolbar'' android,appbarlayout scroll to top,coordinatorlayout toolbar,scroll appbar,appbarlayout scrolling behavior

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *