Reputation: 63
I'm trying to make a CustomScrollView similar to this:
I'm using a SliverAppBar but it seems that it is not the right way. My code so far:
CustomScrollView(
slivers: <Widget>[
SliverAppBar(
expandedHeight: 340,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
background: BackgroundImageWidget(),
centerTitle: true,
// title: Text("Search by cities or activitry in Kreis Kleve"),
title: SearchButtonWidget(),
),
),
),
SliverList(...)
What I get:
I cant figure out why the SearchButtonWidget is so huge at first. When it's shrinked it has the right size. Is sliverAppBar with fliexibleSpace even the right approach?
Edit: can someone also tell me how to make the search button overlapping with the widget below? I guess sliverAppBar can't do that.
Edit 2: maybe it's a white background added under the image. I need to investigate this.
Upvotes: 1
Views: 223
Reputation: 978
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
top: true,
child: CustomScrollView(
slivers: <Widget>[
SliverPersistentHeader(
delegate: MySliverAppBar(
expandedHeight: 250,
title: Container(
margin: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.all(Radius.circular(5.0))),
child: Row(children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 20.0, right: 10.0),
child: Icon(Icons.search),
),
Expanded(
child: TextFormField(
keyboardType: TextInputType.text,
textInputAction: TextInputAction.done,
cursorColor: Colors.black,
autofocus: false,
decoration: InputDecoration(
filled: true,
fillColor: Colors.transparent,
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
hintText: "Search",
border: InputBorder.none,
disabledBorder: OutlineInputBorder(
borderSide:
new BorderSide(color: Colors.transparent),
borderRadius: new BorderRadius.circular(2),
),
focusedBorder: OutlineInputBorder(
borderSide:
new BorderSide(color: Colors.transparent),
borderRadius: new BorderRadius.circular(2),
)),
),
)
]),
)),
pinned: true,
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Container(
child: ListTile(
title: Text("${index}a"),
));
}, childCount: 25))
],
),
),
);
}
.
class MySliverAppBar extends SliverPersistentHeaderDelegate {
final double expandedHeight;
final Widget title;
MySliverAppBar({@required this.expandedHeight, this.title});
final _avatarMarginTween = EdgeInsetsTween(
begin: EdgeInsets.only(bottom: 20),
end: EdgeInsets.only(
bottom: 0.0,
));
final _searchMarginTween = EdgeInsetsTween(
begin: EdgeInsets.only(bottom: 0),
end: EdgeInsets.only(bottom: 8,));
final _avatarAlignTween =
AlignmentTween(begin: Alignment.bottomCenter, end: Alignment.center);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
double tempVal = 75 * maxExtent / 100;
final progress = shrinkOffset > tempVal ? 1.0 : shrinkOffset / tempVal;
final avatarMargin = _avatarMarginTween.lerp(progress);
final searchMargin = _searchMarginTween.lerp(progress);
final searchAlignment = progress > 0.8 ? _avatarAlignTween.lerp(progress) : _avatarAlignTween.lerp(0);
return Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
Padding(
padding: avatarMargin,
child: Image.network(
"https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
fit: BoxFit.cover,
),
),
Center(
child: Opacity(
opacity: shrinkOffset / expandedHeight > 0.7 ? shrinkOffset / expandedHeight : 0.0,
child: Container(
color: Colors.red,
)
),
),
Padding(
padding: searchMargin,
child: Align(
alignment: Alignment.bottomCenter,
child: title,
),
)
],
);
}
@override
double get maxExtent => expandedHeight;
@override
double get minExtent => kToolbarHeight;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
}
Upvotes: 4