Closed bunopus closed 6 years ago
Hi @bunopus, thanks for the feedback 😃. All the slivers are in a CustomScrollView I presume? I am working on a way to have Nested SliverStickyHeader for another feature, but for now I am stucked 😞 . I will have another look to this thanks to your example. I will keep you posted.
I reproduced the issue, and saw that the SliverStickyHeader
was painted under the AppBar. I think I will have to play with the SliverOverlapAbsorber
to fix this.
I found how to do it :grin:!
It's a little bit complex since you'll have to play with SliverOverlapAbsorber
. If you find a simpler solution will you share it here please?
You can find the entire code for the view above here: https://gist.github.com/letsar/2e3cc98d328b3e84170abacf154e545f
@letsar Wow! 😍 Thank you so much! Will try it right now!
You're welcome 😄 . If you find this library useful, don't hesitate to ⭐️ it 😉
Tried your solution, and noticed one thing: app bar title ("Main AppBar") remains on the screen with tab bar. It's not exactly what i want. I think user don't need to see title all the time. In the original Google IO app (in first post) app bar title hides when user scrolls page. Maybe you know how to achieve that? Found PR https://github.com/flutter/flutter/pull/8345 and it says that you can pass floating: true, pinned: true
but it doesn't work :-(
Achieved this by adding another SliverAppBar
:-)
https://gist.github.com/bunopus/4a99dc9def2932e0aff2629f3905093a#file-tab_bar_view-dart-L36-L39
Thanks for your help!
Your're welcome and yes you're right it's not exactly what you wanted but it's more a SliverAppBar
issue than a SliverStickyHeader
one :wink:.
@bunopus You said you achieved this by adding another SliverAppBar but this means you have 2 SliverAppBars? Your gist link code gives me 2 x bars.
https://gist.github.com/bunopus/4a99dc9def2932e0aff2629f3905093a#file-tab_bar_view-dart-L36-L39
How did you make sure the second SliverAppBar ONLY has the TabBar in it?
@workerbee22
How did you make sure the second SliverAppBar ONLY has the TabBar in it? Actually it turned out that it leads to bugs, so i leave it with Tab Bar on the screen, as Romain showed few messages above.
Thanks @bunopus looks like that might be the only option at this stage. I can get it to work just like the Google I/O app where the AppBar bit of the SliverAppBar does in fact scroll off screen leaving just the TabBar pinned.
To see this use this code in this issue: https://github.com/flutter/flutter/issues/17518 , but with SliverAppBar having floating, pinned and snap all set to true.
!!! But as soon as I add flutter_sticky_header package inside a CustomScrollView as part of the TabBarView it stops working ie. AppBar bit of SliverAppBar no longer scrolls off screen.
So it seems like you can have either the floating app bar at the top OR sticky headers, but not both.
This fork has commits related to nested SliverStickyHeader :)
Is there an updated solution for this issue? This does not appear to work when using tabs and the nested scroll view, I'm looking to be able to pin headers that are inside of a custom scroll view in a tab bar view in the body of a nested scroll view.
When testing, my application crashed while changing tabs, because the handle did not remove listeners correctly. I needed to add the 'detach' function and remove the listener accordingly.
@override
void detach() {
handle.removeListener(markNeedsLayout);
super.detach();
}
Here are the snippets if anyone is interested.
/// A sliver that has a sliver geometry based on the values stored in a
/// [SliverOverlapAbsorberHandle].
///
/// The [RenderSliverOverlapAbsorber] must be an earlier descendant of a common
/// ancestor [RenderViewport] (probably a [RenderNestedScrollViewViewport]), so
/// that it will always be laid out before the [RenderSliverObstructionInjector]
/// during a particular frame.
class RenderSliverObstructionInjector extends RenderSliverOverlapInjector {
/// Creates a sliver that is as tall as the value of the given [handle]'s extent.
///
/// The [handle] must not be null.
RenderSliverObstructionInjector({
required SliverOverlapAbsorberHandle handle,
RenderSliver? child,
}) : _handle = handle,
super(handle: handle);
double _currentLayoutExtent = 0;
double _currentMaxExtent = 0;
/// The object that specifies how wide to make the gap injected by this render
/// object.
///
/// This should be a handle owned by a [RenderSliverOverlapAbsorber] and a
/// [RenderNestedScrollViewViewport].
@override
SliverOverlapAbsorberHandle get handle => _handle;
SliverOverlapAbsorberHandle _handle;
@override
set handle(SliverOverlapAbsorberHandle value) {
if (handle == value) return;
if (attached) {
handle.removeListener(markNeedsLayout);
}
_handle = value;
if (attached) {
handle.addListener(markNeedsLayout);
if (handle.layoutExtent != _currentLayoutExtent ||
handle.scrollExtent != _currentMaxExtent) markNeedsLayout();
}
}
@override
void attach(PipelineOwner owner) {
super.attach(owner);
handle.addListener(markNeedsLayout);
if (handle.layoutExtent != _currentLayoutExtent ||
handle.scrollExtent != _currentMaxExtent) {
markNeedsLayout();
}
}
@override
void detach() {
handle.removeListener(markNeedsLayout);
super.detach();
}
@override
void performLayout() {
_currentLayoutExtent = handle.layoutExtent ?? 0;
_currentMaxExtent = handle.layoutExtent ?? 0;
geometry = SliverGeometry(
scrollExtent: 0.0,
paintExtent: _currentLayoutExtent,
maxPaintExtent: _currentMaxExtent,
);
}
}
class SliverObstructionInjector extends SliverOverlapInjector {
/// Creates a sliver that is as tall as the value of the given [handle]'s
/// layout extent.
///
/// The [handle] must not be null.
///
const SliverObstructionInjector(
{super.key, required SliverOverlapAbsorberHandle handle, super.sliver})
: super(handle: handle);
@override
RenderSliverObstructionInjector createRenderObject(BuildContext context) {
return RenderSliverObstructionInjector(
handle: handle,
);
}
}
Thank you for your library, it's super useful. I have one question: Is it possible to achieve something like this:
As you can see header with dates sticks to the screen as well as the side header with time (it is a https://github.com/google/iosched app). Example app have great section with side headers, but i tried to nest
SliverStickyHeader
and it doesn't work. Second Header doesn't stick to screen.Code