Reputation: 480
I want my appbar to act as a fixed appbar when it's scrolled down, or user's searching something.
SliverAppBar(
title: new TextField(
style: Theme.of(context).primaryTextTheme.title,
decoration: InputDecoration(
hintText: '검색',
),
),
),
But I want to draw it as a flexible appbar when it's scrolled up and user's not searching.
flexibleSpace: new FlexibleSpaceBar(
centerTitle: false,
title: new TextField(
style: Theme.of(context).primaryTextTheme.title,
decoration: InputDecoration(
hintText: '검색',
),
),
background: Stack(
fit: StackFit.expand,
children: <Widget>[
SizedBox(
height: 256.0,
child: Container(
child: Padding(
padding: const EdgeInsets.only(top: 24.0),
child: Column(
children: <Widget>[
Align(
alignment: Alignment.topLeft,
child: FlutterLogo(
size: 64.0,
),
),
Padding(padding: const EdgeInsets.only(bottom: 24.0)),
ListTile(
title: Text('Some Text'),
),
],
),
),
),
),
// This gradient ensures that the toolbar icons are distinct
// against the background image.
],
),
),
Search field is transformed to top-right little bit when scrolled up with second approach.
Upvotes: 2
Views: 4050
Reputation: 17854
Here's my code with a TextField and Tabs in a SliverAppBar:
NestedScrollView(
controller: model.mainScrollController,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
/// https://github.com/flutter/flutter/issues/54059
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: SliverAppBar(
automaticallyImplyLeading: false,
pinned: true,
floating: true,
snap: true,
expandedHeight: 100,
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.pin,
background: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Row(
children: [
BackButton(
color: Colors.white,
),
Flexible(
child: TextField(
controller: model.searchController,
decoration: InputDecoration(
focusColor: Colors.blueAccent,
hoverColor: Colors.blueAccent,
fillColor: Colors.white,
filled: true,
isDense: true,
prefixIconConstraints: BoxConstraints(maxHeight: 24, maxWidth: 48),
prefixIcon: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Icon(Icons.search_outlined),
),
hintText: 'Search...'),
),
),
IconButton(
icon: Icon(
Icons.add,
color: Colors.white,
),
onPressed: () {
ExtendedNavigator.named('topNav').push(Routes.newExerciseView);
},
tooltip: 'Create Exercise',
),
],
),
),
),
bottom: TabBar(
labelPadding: EdgeInsets.only(bottom: 8),
indicatorWeight: 3,
indicatorSize: TabBarIndicatorSize.label,
tabs: [
Text('All'),
Text('Custom'),
Text('Favorites'),
],
),
),
),
];
},
body: TabBarView(
children: [
AllExercises(),
CustomExercises(),
FavoriteExercises(),
]),
),
There's a few key pieces that make this work right, the first being that you need to use the SliverAppBar's flexibleSpace property to add your search widget. If you try adding it in the title property, the TextField just get's squished but never goes off screen.
Second, make sure that the collapseMode of the FlexibleSpaceBar is set to CollapseMode.pin. This makes it so that the contents of the flexibleSpace scroll off screen and don't change size.
And finally, set pinned on the sliverAppBar to true so the TabBar sticks.
Upvotes: 0
Reputation: 1779
I've written a getMaterialSerach();
method in this gist which has the exact material search view you need. just add getMaterialSearch() from this in your appBar:
widget like below.
here is the gist for getMaterialSearch();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: getMaterialSearchBar(),
body: Center(
child: Container(),
),
);
}
Upvotes: 0
Reputation: 480
The effect can be achieved by moving title content to another SliverList.
Remove flexibleSpace
from SliverAppBar, and move contents of flexibleSpace.background to SliverList before the SliverAppBar.
Example:
@override
Widget build(BuildContext context) {
return new CustomScrollView(
slivers: <Widget>[
new SliverList(
delegate: new SliverChildListDelegate(<Widget>[
Align(
alignment: Alignment.topLeft,
child: FlutterLogo(size: 64.0),
),
ListTile(
title: Text('Some Text'),
),
ListTile(),
])),
new SliverAppBar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
elevation: 0.0,
automaticallyImplyLeading: false,
pinned: true,
floating: false,
title: new TextField(
focusNode: _searchFocusNode,
style: Theme.of(context).primaryTextTheme.title,
decoration: InputDecoration(
border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
suffixIcon: Icon(Icons.search),
hintText: '검색',
),
),
),
new SliverList(
delegate: new SliverChildListDelegate(List.generate(
100,
(i) => ListTile(
title: Text('Scroll'),
)).toList()),
),
],
);
}
Upvotes: 2