Animated Container with scrolling list - Flutter - flutter

I have a fairly complicated screen I am trying to implement in Flutter.
It's a scrollview with a parallax background and...kind of a collapsing toolbar.
I know I have to probably use a NestedScrollView and SliverAppBar(?), but not sure where to start on implementing. I think a picture would best show what I am trying to accomplish:
The list starts below a Container. As you scroll the list, the Container shrinks to a smaller Container and is pinned to the top. Does that make sense? Any help would be greatly appreciated!

This is using SliverAppBar with expandedHeight. I will encourage checking this video.
#override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
expandedHeight: constraints.maxHeight * .3,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text("Title"),
background: Container(
color: Colors.pink,
),
),
),
SliverToBoxAdapter(
child: Container(
height: constraints.maxHeight * 4,
color: Colors.deepOrange,
),
)
],
),
),
);
}

Related

Flutter smoothly scaling app bars title on scroll

for now I have mock of view as presented. I want this app bars title to be twice as big when I'm on the top of the screen with no buttons, and scale smoothly back to current form with two buttons when I scroll down. I tried to experiment with sliverappbar but without effect. I use here scaffold with standard app bar. Is there a convenient way to achieve it, or I have to write it myself. I'd be thankful for any advice.
EDIT: Something like showed here gif
You can use CustomScrollView with Slivers to achieve your desired result. I'm sharing an example for this you can customize it as per your need.
CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
expandedHeight: 120,
flexibleSpace: FlexibleSpaceBar(
title: Text("Barb's Latest",style: TextStyle(fontSize: 30),),titlePadding: EdgeInsets.all(15),
),automaticallyImplyLeading: true,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Container(
height: 100,
margin: EdgeInsets.only(bottom: 10),
color: Colors.red,
),
childCount: 50))
],
)

Blank space above Stepper in Flutter CustomScrollView

I'm currently working on a screen that includes a Flutter Stepper within a CustomScrollView. There is a SliverAppBar and the Stepper is wrapped in a SliverToBoxAdapter and a Padding. Unfortunately, there is a blank space above the Stepper that doesn't seem to belong to the Padding or the Box Adapter. If I add the Stepper to a normal Scaffold, this space is not visible. Please see the attached screenshots. Does anyone know how to solve that? Thanks in advance!
Here is the code:
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
snap: false,
floating: false,
automaticallyImplyLeading: false,
expandedHeight: 250,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20))),
flexibleSpace: FlexibleSpaceBar(...),
),
SliverPadding(
padding: const EdgeInsets.all(10),
sliver: SliverToBoxAdapter(
child: Stepper(...),
),
)
],
),
);
}
And here are some screenshots:
Screen Layout
Screen Layout with Debug Paint
I read about this in another thread just with a ListView instead of a Stepper. The solution is to wrap the Stepper with MediaQuery.removePadding(...) and set the removeTop attribute to true.
SliverPadding(
padding: const EdgeInsets.all(10),
sliver: SliverToBoxAdapter(
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: Stepper(...)
)
)
)

how to get a full size height of customscrollview widget in flutter?

I want to get the whole height of CustomScrollView widget. So I made a below code but it's not working.
#override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => getSizeAndPosition());
}
getSizeAndPosition() {
RenderBox _customScrollBox =
_customScrollKey.currentContext.findRenderObject();
_customScrollSize = _customScrollBox.size;
_customScrollPosition = _customScrollBox.localToGlobal(Offset.zero);
print(_customScrollSize.height);
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _customScrollKey,
appBar: _appbar(),
body: CustomScrollView(
controller: _controller,
slivers: [
SliverList(
delegate: SliverChildListDelegate([
_titleSection(),
_thumnail(),
SizedBox(
height: 40,
),
])),
],
),
);
}
The height obtained by this code does not take into account the height of the list in the customScrollview. I mean, _customScrollSize.height and MediaQuery.of(context).size.width are the same.
I want this function
_controller.addListener(() {
setState(() {
if (_controller.offset < 0) {
scrollHeight = 0;
} else {
scrollHeight = _controller.offset;
}
});
});
Container(
width: size.width * (scrollHeight / _customScrollSize.height),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1)),
With the above code, '_customScrollSize.height' does not reflect the overall height and therefore the function is not implemented properly. Is there any good way to use it in this situation?
CustomScrollView
A ScrollView that creates custom scroll effects using slivers.
A CustomScrollView lets you supply slivers directly to create various scrolling effects, such as lists, grids, and expanding headers. For example, to create a scroll view that contains an expanding app bar followed by a list and a grid, use a list of three slivers: SliverAppBar, SliverList, and SliverGrid.
In your case do remove the appBar and use a sliverAppBar withing the custome scrollview , and you can use sliverfillRemaining widget for your other children
example
CustomScrollView(
slivers: <Widget>[
const SliverAppBar(
pinned: true,
expandedHeight: 250.0,
flexibleSpace: FlexibleSpaceBar(
title: Text('Demo'),
),
),
SliverList(
delegate: SliverChildListDelegate([
_titleSection(),
_thumnail(),
SizedBox(
height: 40,
),
])),
...

Flutter: combining SliverAppbar with Column widget

I'm trying to make an event page for an app where user can view events that have a banner image and some other useful information. I really like the idea of implementing a SliverAppBar with the banner, so that the user can scroll to see more information. For this I seem to need a CustomScrollView with a SliverAppBar and FlexibleSpaceBar.
All tutorials I have seen online assume that the rest of the screen should be a list of sorts, but I rather want something like a Column widget. A Column has unbounded height, however, which causes overflow errors in the CustomScrollView. I could wrap it in a Container with specified height, but the contents of the body are of variable size, so that is not ideal. Is there a way to have a SliverAppBar and a Column work side by side?
I want something along the lines of this:
class ActivityPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(slivers: [
SliverAppBar(
flexibleSpace: FlexibleSpaceBar(
background: Image(someImage),
),
expandedHeight: Image,
floating: false,
pinned: true,
snap: false,
),
Column(
children: [
someChildren,
]
),
)
]),
),
);
}
It should be possible, because it seems to me a somewhat common pattern, but I have looked around a lot and I can only find examples where the body consists of lists...
For anyone having the same struggle: here's the solution I just found:
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
backgroundColor: this.color,
flexibleSpace: FlexibleSpaceBar(
background: YourImage(),
),
)
];
},
body: Container(
child: Builder(builder: (context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
WidgetOne(),
WidgetTwo()
]);
})),
),
)),
);
}
Use SliverList and SliverChildListDelegate instead of a Column.
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
expandedHeight: 200,
flexibleSpace: FlexibleSpaceBar(
background: Container(color: Colors.green),
),
),
SliverList(
delegate: SliverChildListDelegate([
Container(color: Colors.yellow, height: 400),
Container(color: Colors.red, height: 800),
]),
),
],
),
);
}
Use ListView instead of Column. ListView has dynamic size
For me the best way is to use SliverToBoxAdapter. Just wrap your Column in a Container and then wrap this Container in a SliverToBoxAdapter and it should work fine.

Using flexible SliverAppBar as non-top element

I'm trying to display a flexible SliverAppBar below a custom app bar (let's say it's a container with a height of 80.0).
When making the SliverAppBar the top element, it works fine, but when it's the second one, there is a top-padding as big as the Android UI interface.
Scaffold(
body: Column(children: <Widget>[
Container(height: 80.0),
Expanded(child: _content())
]),
);
_content()
return CustomScrollView(slivers: <Widget>[
SliverAppBar(
backgroundColor: Colors.red,
leading: PopContentButton(),
title: Text('Test'),
snap: true,
pinned: true,
floating: true,
bottom: TabBar(
tabs: _tabs(),
controller: TabControllerExtended(length: 4, vsync: this),
),
),
SliverList(delegate: new SliverChildListDelegate(buildTextViews(50)))
]);
This is not how it should look:
(source: bilder-upload.eu)
It should look like:
(source: bilder-upload.eu)
Wrap you - SliverAppBar with MediaQuery.removePadding.
Updated Code :
....
MediaQuery.removePadding(
context: context,
removeTop: true,
child: SliverAppBar(
...