Fixed
Status Update
Comments
al...@android.com <al...@android.com>
ri...@gmail.com <ri...@gmail.com> #2
Confirmed. I can only recreate on API 16 though.
Workaround for now is to set app:borderWidth="0dp"
Workaround for now is to set app:borderWidth="0dp"
da...@gmail.com <da...@gmail.com> #3
app:borderWidth="0dp" also fixes elevation issues on 21+. Without it, no matter how much elevation is specified the FAB is flat.
me...@yanghui.name <me...@yanghui.name> #4
<android.support.design.widget.FloatingActionButton
xmlns:app="http://schemas.android.com/apk/res-auto "
app:borderWidth="0dp"
android:id="@+id/fab_1"
android:layout_marginBottom="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:src="@drawable/abc_ic_clear_mtrl_alpha"/>
And i still get a square on lollipop devices
xmlns:app="
app:borderWidth="0dp"
android:id="@+id/fab_1"
android:layout_marginBottom="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:src="@drawable/abc_ic_clear_mtrl_alpha"/>
And i still get a square on lollipop devices
ch...@google.com <ch...@google.com> #5
testes on nexus 5 os version 5.1
al...@gmail.com <al...@gmail.com> #6
Fixed internally. Will be out soon.
al...@gmail.com <al...@gmail.com> #7
I also saw another issue where the CollapsingActionBarLayout would sometimes not 'uncollapse' on Kitkat when scrolling down in the RecyclerView. This might be due to my nesting of ImageView in NestedScrollView though.
am...@gmail.com <am...@gmail.com> #8
ch...@google.com <ch...@google.com>
ch...@google.com <ch...@google.com> #9
For those that still have a square button after adding app:borderWidth="0dp", I found that setting android:background was causing the issue for me. Set android:backgroundTint instead.
ch...@google.com <ch...@google.com> #10
[Comment deleted]
na...@gmail.com <na...@gmail.com> #11
For those whom nothing else worked, this is the xml layout I used in the end and worked like a charm among all the devices I used:
<android.support.design.widget.FloatingActionButton
android:id="@+id/ddd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
app:elevation="@dimen/floating_button_elevation"
app:borderWidth="0dp"
app:rippleColor="@color/red"
app:backgroundTint="@color/blue" />
Notice the "app:backgroundTint" instead of "android:backgroundTint"
Hope it helps!
<android.support.design.widget.FloatingActionButton
android:id="@+id/ddd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
app:elevation="@dimen/floating_button_elevation"
app:borderWidth="0dp"
app:rippleColor="@color/red"
app:backgroundTint="@color/blue" />
Notice the "app:backgroundTint" instead of "android:backgroundTint"
Hope it helps!
[Deleted User] <[Deleted User]> #12
@Chris,
While we are waiting for a future release to fix this bug, can you share some example code on using ViewDragHelper in AppBarLayout's custom behavior to fix this?
While we are waiting for a future release to fix this bug, can you share some example code on using ViewDragHelper in AppBarLayout's custom behavior to fix this?
ch...@google.com <ch...@google.com> #13
In my case after adding app:borderWidth="0dp" still button was square. Because before using this newly released support lib, i used google android sample in which i end up creating "fab_background" file which was causing this issue. After removing said file button is appearing as circle.
kr...@gmail.com <kr...@gmail.com> #14
Released in v22.2.1.
ku...@gmail.com <ku...@gmail.com> #15
FAB still seems to be square in API 16 after new release.
ch...@google.com <ch...@google.com> #16
#17: are you changing the FAB's background?
[Deleted User] <[Deleted User]> #17
FAB is still square on lollipop devices, i noticed that setting borderWidth to a greater value doesn't exactly fix things but reduces the square drawables size so it resides inside the circular view but is easily distinguished and without giving borderWidth the drawable takes up the whole width and height available to it. Is there a problem with how CircularDrawableForLollipop is implemented??
[Deleted User] <[Deleted User]> #18
This seems to still be an issue. Im using support libs 23.0.0, setting app:backgroundTint seems to work as a workaround, has a cause been found for this?
ch...@google.com <ch...@google.com> #19
i tried app:borderWidth="0dp" and "app:backgroundTint" too but however app:backgroundTint didn't solve for the api 22+
[Deleted User] <[Deleted User]> #20
Always update to the latest version before adding a 'me too'. This is no longer reproducible.
[Deleted User] <[Deleted User]> #21
#22, have you upgraded appCompat to v23 as well? appCompat transitively depends on support, using the old appCompat with new support lib will cause problems.
[Deleted User] <[Deleted User]> #22
Yeah, everything is upgraded to v23. Target SDK is 23 as well.
ho...@gmail.com <ho...@gmail.com> #23
#22, #23: it's a known issue, see #183166
se...@gmail.com <se...@gmail.com> #24
I have to touch the content inside NestedScrollView or RecyclerView to make CollapsingToolbarLayout responds to scroll. If I don't touch the content first, the CollapsingToolbarLayout still cannot be scrolled. Is there any workaround for this issue?
ch...@google.com <ch...@google.com> #25
#26: It's the best we can do.
ri...@gmail.com <ri...@gmail.com> #26
I see the same at #26 and have a workaround, albeit a flimsy one.
The problem
=========
After sticking AppBarLayout.Behavior.onInterceptTouchEvent(CoordinatorLayout, AppBarLayout, MotionEvent) and AppBarLayout.Behavior.onTouchEvent(CoordinatorLayout, AppBarLayout, MotionEvent) through the debugger, I observed it was getting stuck on the conditional statement for when the action is ACTION_DOWN. The statement reads;
if (parent.isPointInChildBounds(child, x, y) && canDragAppBarLayout()) {
mLastMotionY = y;
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
}
isPointInChildBounds(View, int, int) returns true, and canDragAppBarLayout() returns false. The implementation of canDragAppBarLayout() looks like the following;
private boolean canDragAppBarLayout() {
if (mLastNestedScrollingChildRef != null) {
final View view = mLastNestedScrollingChildRef.get();
return view != null && view.isShown() && !ViewCompat.canScrollVertically(view, -1);
}
return false;
}
mLastNestedScrollingChildRef is defined as: private WeakReference<View> mLastNestedScrollingChildRef; (of course, initialised to null)
This member is only read from inside canDragAppBarLayout(). The only time it is assigned is as null inside onStartNestedScroll() and as as WeakReference to the target nested scrolling child in onStopNestedScroll(CoordinatorLayout, AppBarLayout, View). As you'll see in the implementation of canDragAppBarLayout() is that it needs to be non-null (and the WeakReference.get() needs to be non-null) too, as well as the View being shown and being able to scroll vertically before canDragAppBarLayout() returns true.
The problem is caused because mLastNestedScrollingChildRef is not set until after the first scroll of the NestedScrollingChild has finished, which means you have to scroll the bottom at least once before you can scroll the top.
The workaround
============
*This will only work on the 23.0.0 release of the support library and may break on any future version*
Within initialisation of your View hierarchy...
- Get a reference to your scrolling View (NestedScrollView or RecyclerView) and CoordinatorLayout.
final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
- Get a reference to the AppBarLayout.Behavior.
final AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appBarLayout);
final CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
final AppBarLayout.Behavior appBarBehavior = (AppBarLayout.Behavior) appBarLayoutParams.getBehavior();
*If appBarBehavior is null for you, you might need to set it in the XML by doing the following*
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
*app:layout_behavior="android.support.design.widget.AppBarLayout$Behavior"*>
- Perform hackery! This is where Chris cries "Nooooooooooooooo!"
appBarBehavior.onStopNestedScroll(coordinatorLayout, appBarLayout, recyclerView);
Why? Because above you'll see that mLastNestedScrollingChildRef is only set in onStopNestedScroll(CoordinatorLayout, AppBarLayout, View). In 23.0.0 of the design library, it appears to be harmless to call this, but this may not always be the case. Be warned.
And that's it, the top will now be able to be scrolled before the bottom (vice-versa still works).
*What if I use a ViewPager?*
It gets a little more complicated here. You need to listen out for page changes (see ViewPager.OnPageChangeListener). Instead of calling appBarBehavior.onStopNestedScroll(CoordinatorLayout, AppBarLayout, View) at View hierarchy initialisation, you need to call it *every time a page changes*. So if you're using FragmentPagerAdapter or FragmentStatePagerAdapter, you will need to get the current Fragment being shown, call its Fragment.getView() and find your scrolling View inside there. Then you pass that through to appBarBehavior.onStopNestedScroll(CoordinatorLayout, AppBarLayout, View) and that should work between page changes.
Proposed fix for support library
========================
Have a setter inside AppBarLayout.Behavior which allows third party developers to give it a reference to the current scrollable View, and assign this to mLastNestedScrollingChildRef.
Hopefully this is helpful. If anybody has found any better workarounds then please do share.
The problem
=========
After sticking AppBarLayout.Behavior.onInterceptTouchEvent(CoordinatorLayout, AppBarLayout, MotionEvent) and AppBarLayout.Behavior.onTouchEvent(CoordinatorLayout, AppBarLayout, MotionEvent) through the debugger, I observed it was getting stuck on the conditional statement for when the action is ACTION_DOWN. The statement reads;
if (parent.isPointInChildBounds(child, x, y) && canDragAppBarLayout()) {
mLastMotionY = y;
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
}
isPointInChildBounds(View, int, int) returns true, and canDragAppBarLayout() returns false. The implementation of canDragAppBarLayout() looks like the following;
private boolean canDragAppBarLayout() {
if (mLastNestedScrollingChildRef != null) {
final View view = mLastNestedScrollingChildRef.get();
return view != null && view.isShown() && !ViewCompat.canScrollVertically(view, -1);
}
return false;
}
mLastNestedScrollingChildRef is defined as: private WeakReference<View> mLastNestedScrollingChildRef; (of course, initialised to null)
This member is only read from inside canDragAppBarLayout(). The only time it is assigned is as null inside onStartNestedScroll() and as as WeakReference to the target nested scrolling child in onStopNestedScroll(CoordinatorLayout, AppBarLayout, View). As you'll see in the implementation of canDragAppBarLayout() is that it needs to be non-null (and the WeakReference.get() needs to be non-null) too, as well as the View being shown and being able to scroll vertically before canDragAppBarLayout() returns true.
The problem is caused because mLastNestedScrollingChildRef is not set until after the first scroll of the NestedScrollingChild has finished, which means you have to scroll the bottom at least once before you can scroll the top.
The workaround
============
*This will only work on the 23.0.0 release of the support library and may break on any future version*
Within initialisation of your View hierarchy...
- Get a reference to your scrolling View (NestedScrollView or RecyclerView) and CoordinatorLayout.
final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
- Get a reference to the AppBarLayout.Behavior.
final AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appBarLayout);
final CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
final AppBarLayout.Behavior appBarBehavior = (AppBarLayout.Behavior) appBarLayoutParams.getBehavior();
*If appBarBehavior is null for you, you might need to set it in the XML by doing the following*
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
*app:layout_behavior="android.support.design.widget.AppBarLayout$Behavior"*>
- Perform hackery! This is where Chris cries "Nooooooooooooooo!"
appBarBehavior.onStopNestedScroll(coordinatorLayout, appBarLayout, recyclerView);
Why? Because above you'll see that mLastNestedScrollingChildRef is only set in onStopNestedScroll(CoordinatorLayout, AppBarLayout, View). In 23.0.0 of the design library, it appears to be harmless to call this, but this may not always be the case. Be warned.
And that's it, the top will now be able to be scrolled before the bottom (vice-versa still works).
*What if I use a ViewPager?*
It gets a little more complicated here. You need to listen out for page changes (see ViewPager.OnPageChangeListener). Instead of calling appBarBehavior.onStopNestedScroll(CoordinatorLayout, AppBarLayout, View) at View hierarchy initialisation, you need to call it *every time a page changes*. So if you're using FragmentPagerAdapter or FragmentStatePagerAdapter, you will need to get the current Fragment being shown, call its Fragment.getView() and find your scrolling View inside there. Then you pass that through to appBarBehavior.onStopNestedScroll(CoordinatorLayout, AppBarLayout, View) and that should work between page changes.
Proposed fix for support library
========================
Have a setter inside AppBarLayout.Behavior which allows third party developers to give it a reference to the current scrollable View, and assign this to mLastNestedScrollingChildRef.
Hopefully this is helpful. If anybody has found any better workarounds then please do share.
ch...@google.com <ch...@google.com> #27
#28: Haha, nice detective work.
The problem is that the scrolling child isn't necessarily a direct descendent, and we don't want to get into the game of searching the sub-tree for a potential scrolling child (which could easily be wrong).
Therefore we wait until we're given the nested scrolling child. This only happens after the first scroll though.
I'll have a think if there's anything else we can do.
The problem is that the scrolling child isn't necessarily a direct descendent, and we don't want to get into the game of searching the sub-tree for a potential scrolling child (which could easily be wrong).
Therefore we wait until we're given the nested scrolling child. This only happens after the first scroll though.
I'll have a think if there's anything else we can do.
ri...@gmail.com <ri...@gmail.com> #28
Hi Chris,
That is exactly what I suspected for the reason why it's like this. Unfortunately it gives a weird user interaction though, making the scrolling behaviour inconsistent and unpredictable.
I did have a think about how it should really be in the support library, and I recognised that it would be silly to do a deep search of the View hierarchy tree, from the CoordinatorLayout onwards, because you could easily have more than one nested scrolling child in the hierarchy if you have a ViewPager or so. So for that reason, I think it's entirely reasonable that the onus should be placed upon the third-party developer to tell the CoordinatorLayout (or AppBarLayout, or the Behaviors) what is the current scrolling View.
This could either be as a setter like I described above in #28, or possibly a callback mechanism whereby the the Behavior queries the callback upon every touch event to ask what the current scrolling View is.
As a bonus, this mechanism can be used to signal whether the third-party developer wishes the AppBarLayout to be draggable at all. By not setting the scrollable View, by not setting a callback or by returning null from the callback, the third-party developer is saying that they do not wish the AppBarLayout to be dragged.
Failing that, even having canDragAppBarLayout() as a public method that can be overridden would be great, because the third-party developer can define their own AppBarLayout.Behavior subclass that redefines that method so that they can provide their own logic as to whether it should be draggable or not.
Thanks for the work on this btw! I've been working with the CoordinatorLayout stuff a lot recently, hence the detective work ;)
That is exactly what I suspected for the reason why it's like this. Unfortunately it gives a weird user interaction though, making the scrolling behaviour inconsistent and unpredictable.
I did have a think about how it should really be in the support library, and I recognised that it would be silly to do a deep search of the View hierarchy tree, from the CoordinatorLayout onwards, because you could easily have more than one nested scrolling child in the hierarchy if you have a ViewPager or so. So for that reason, I think it's entirely reasonable that the onus should be placed upon the third-party developer to tell the CoordinatorLayout (or AppBarLayout, or the Behaviors) what is the current scrolling View.
This could either be as a setter like I described above in #28, or possibly a callback mechanism whereby the the Behavior queries the callback upon every touch event to ask what the current scrolling View is.
As a bonus, this mechanism can be used to signal whether the third-party developer wishes the AppBarLayout to be draggable at all. By not setting the scrollable View, by not setting a callback or by returning null from the callback, the third-party developer is saying that they do not wish the AppBarLayout to be dragged.
Failing that, even having canDragAppBarLayout() as a public method that can be overridden would be great, because the third-party developer can define their own AppBarLayout.Behavior subclass that redefines that method so that they can provide their own logic as to whether it should be draggable or not.
Thanks for the work on this btw! I've been working with the CoordinatorLayout stuff a lot recently, hence the detective work ;)
ch...@google.com <ch...@google.com> #29
Yeah, I think that's the better option: making canDragAppBarLayout() some sort of public API. Having a setter for the scrolling view feels wtong.
br...@trunkclub.com <br...@trunkclub.com> #30
[Comment deleted]
ma...@gmail.com <ma...@gmail.com> #31
#31: Chris, could you update this ticket's status from Released if you do indeed plan to move forward with the canDragAppBarLayout fix, or create a new ticket? I'm relying on the workaround from #28 for now.
ma...@gmail.com <ma...@gmail.com> #32
Also relaying on the #28 work around, waiting for update on this bug.
ch...@google.com <ch...@google.com> #33
I've got something out for review which implements a Callback. It's also improves the default behavior.
ch...@google.com <ch...@google.com>
ry...@gmail.com <ry...@gmail.com> #34
Adding default scroll behavior support to more than just a single, scrollable, child view of the CoordinatorLayout would be much appreciated (e.g. a header view to the nested scroll view).
ch...@google.com <ch...@google.com> #35
#37: Not going to happen, as things would get complex very quickly.
ry...@gmail.com <ry...@gmail.com> #36
#38 Understandable. Do you have a suggestion for a workaround?
ch...@google.com <ch...@google.com> #37
#39: If it's a header to the scrolling view, then it would logically live in there.
ry...@gmail.com <ry...@gmail.com> #38
#40: For example, the LinearLayout below should always be visible and above the RecyclerView without being an element in the RecyclerView. The layout is fine, but this introduces an issue where attempting to scroll over the LinearLayout does not scroll the CoordinatorLayout.
...
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/button_layout_height"
android:orientation="horizontal"
android:background="@color/button_layout"
android:gravity="center_vertical">
<!-- three buttons -->
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/button_layout_height"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
...
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/button_layout_height"
android:orientation="horizontal"
android:background="@color/button_layout"
android:gravity="center_vertical">
<!-- three buttons -->
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/button_layout_height"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
ch...@google.com <ch...@google.com> #39
Released in v23.1.0.
sh...@gmail.com <sh...@gmail.com> #40
[Comment deleted]
ni...@gmail.com <ni...@gmail.com> #41
Still have the problem of #3 in v23.1.0. Scrolling is not inertial. Anyone find a solution to this?
ke...@gmail.com <ke...@gmail.com> #42
Version 23.1.1 Same problem as mentioned in #3
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginTop="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
Tried without marginTop - same problem.
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginTop="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
Tried without marginTop - same problem.
ch...@google.com <ch...@google.com> #43
#45: That's not the same bug. Inertial scrolling is a known issue
zx...@gmail.com <zx...@gmail.com> #44
[Comment deleted]
av...@gmail.com <av...@gmail.com> #45
#47: sorry for raising this issue with off-top question, but you mentioned that inertial scrolling is a known issue. Is there any open bug regarding it to subscribe for updates?
I only managed to find this onehttps://code.google.com/p/android/issues/detail?id=179501 and a very fresh one (created 4 days ago) with a patch https://code.google.com/p/android/issues/detail?id=195800 that seems to be related to the same topic. But both of these issues are not assigned to anyone.
Thanks.
I only managed to find this one
Thanks.
[Deleted User] <[Deleted User]> #46
[Comment deleted]
tr...@gmail.com <tr...@gmail.com> #47
I confirm that the bug with not scrollable CollapsingToolbarLayout is fixed. But if you add bottom sheet layout introduced in design lib, the CollapsingToolbarLayout stops scrolling again.
http://stackoverflow.com/questions/36939982/scrolling-is-not-working-with-coordinatorlayout-parallax-image-bottomsheetla/36968467#36968467
[Deleted User] <[Deleted User]> #48
[Comment deleted]
se...@gmail.com <se...@gmail.com> #49
Hi, I have the same bug with not scrollable Collapsing AppBarLayout: here is detailed description on stackoverflow with videos attached and simple project with source code: https://stackoverflow.com/questions/50043779/collapsing-appbarlayout-not-scrolling-with-tablayout-and-nestedscrollview
Appears in version of support library: v27.0.1
Appears in version of support library: v27.0.1
Description
Version used: 22.0.0
Using a CollapsingToolbarLayout and a RecyclerView, you can only scroll from the recyclerView, swiping on the Toolbar has no effect.
Some users have a hard time realizing that this layout can scroll, so only be able to interact with half of it is problematic, especially in landscape where it takes a lot of vertical space.
It would be useful to let the users swipe the same way from the toolbar and the scrolling view.