Pull down to show search bar in flutter? - flutter

do anyone know how to have the screen to pull down and it would show a search icon button and then a search filter bar on the top?
For example in Spotify, there is a search function for the album, that when you pull the screen down and it show a search filter bar to search for music. (i think).

What you're looking for is RefreshIndicator. Which you insert above your ListView/GridView/scroll.

You can use SilverAppBar inside CustomScrollView to do this. Every time u scroll up in any position, appbar will appear
You can checkout preview for this example i write here
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: MyWidget(),
),
);
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers:[
SliverAppBar(
// pinned: true,
floating: true,
snap: true,
title: Text('Your appbar'),
),
SliverFixedExtentList(
itemExtent: 50.0,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: Text('List Item $index'),
);
},
),
),
],
),
);
}
}

Related

How can I achieve a draggable header in bottomsheet modal?

In my flutter app, I’m using a pinned header and a listview within a bottomsheet modal.
The problem usually is that when I overscroll, I have to scroll all the way back to be able to dismiss the modal. I would like to drag the header instead to collapse the bottom sheet modal even when the list is overscrolled.
Does anyone know how I can make the header draggable to achieve this effect?
You can find similar behavior in for example "places" section on Snapchat or the "comments" section of YouTube’s mobile app.
Here is a preview: https://imgur.com/a/fxww2IW
Here is a link to my code snippet: https://dartpad.dev/?id=960bf30a2c288ec1a0a48374b6cdbfd3
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: ElevatedButton(
child: const Text('Show modal'),
onPressed: () => {
showModalBottomSheet(
backgroundColor: Colors.transparent,
clipBehavior: Clip.antiAlias,
context: context,
enableDrag: true,
isDismissible: true,
isScrollControlled: true,
builder: (modalContext) => MyWidget())
},
),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DraggableScrollableSheet(
initialChildSize: 0.5,
minChildSize: 0.5,
maxChildSize: 0.9,
expand: false,
builder: (BuildContext context, ScrollController scrollController) =>
Container(
color: Colors.white,
child: CustomScrollView(
controller: scrollController,
slivers: [
const SliverAppBar(
title: Text("Header Title"),
pinned: true,
),
SliverFillRemaining(
child: ListView.builder(
itemCount: 500,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: const Icon(Icons.list),
trailing: const Text(
"GFG",
style: TextStyle(color: Colors.green, fontSize: 15),
),
title: Text("List item $index"));
}),
),
],
),
),
);
}
}
I have tried using CustomScrollview with Slivers. I expect that dragging the pinned header downwards will also move the bottomsheet downwards as in the image I have shared in the description
Look The solution for your problem is easy make a late ScrollController _scrollController; and put it in your listviewthen put this code in initState
super.initState();
_controller = ScrollController()..addListener(_scrollListener);
void _scrollListener() {`
if (_controller.position.userScrollDirection == ScrollDirection.forward &&
_controller.position.extentAfter >= _controller.position.maxScrollExtent) {
Navigator.pop(context);
}
`}
this mean when my ScrollController go up a little pop out that will close your showModalBottomSheet

Can not fit image and text in AppBar Flutter

I want to place image and text into appbar, but it seems that i cant fit all i want into appbar.
I have this code:
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title:Column(
children: [
Container(
child: Image.asset(
'assets/vecteezy_circle-abstract_1191814.png',
fit: BoxFit.scaleDown,
height: 100,
),
),
Container(
padding: const EdgeInsets.only(top: 15),
child: Text('Text'))
],
),
bottom: TabBar(
tabs: [Tab(text: 'tab 1'), Tab(text: 'tab 2')],
),
),
body: TabBarView(children: [
Text("o"),
Text("kk"),
]),
));
}
and I have such result :
https://i.stack.imgur.com/jzt4o.png
how do I fit it right? so it looks like this:
https://i.stack.imgur.com/r0gum.png
You need to use CustomScrollView with SliverAppBar
look at this example from Flutter Dev
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
final title = 'Floating App Bar';
return MaterialApp(
title: title,
home: Scaffold(
// No appbar provided to the Scaffold, only a body with a
// CustomScrollView.
body: CustomScrollView(
slivers: <Widget>[
// Add the app bar to the CustomScrollView.
SliverAppBar(
// Provide a standard title.
title: Text(title),
// Allows the user to reveal the app bar if they begin scrolling
// back up the list of items.
floating: true,
// Display a placeholder widget to visualize the shrinking size.
flexibleSpace: Placeholder(),
// Make the initial height of the SliverAppBar larger than normal.
expandedHeight: 200,
),
// Next, create a SliverList
SliverList(
// Use a delegate to build items as they're scrolled on screen.
delegate: SliverChildBuilderDelegate(
// The builder function returns a ListTile with a title that
// displays the index of the current item.
(context, index) => ListTile(title: Text('Item #$index')),
// Builds 1000 ListTiles
childCount: 1000,
),
),
],
),
),
);
}
}

Rounded corners with Customscrolview and SliverList / SliverAppBar in Flutter

I'm working on an app in Flutter and want to have the following design of my SliverAppBar with the rounded corners to the bottom in my App. How can I do this when I use slivers?
Design rounded corner
I found the design on Dribbble from a YouTuber who created the app as a tutorial but without using a PageView with Slivers
This is a simplified version of the code I'm using:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: PageView(
children: [
CustomScrollView(
slivers: <Widget>[
SliverAppBar(
backgroundColor: Colors.red,
expandedHeight: 250.0,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Card(
child: ListTile(
title: Text('something'),
),
);
},
childCount: 10,
))
],
),
],
),
),
);
}
}
use SliverPadding like this:
DefaultTabController(
child:NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return [
SliverPadding(
padding: new EdgeInsets.only(top: 5.0),
sliver: new SliverList(
delegate: new SliverChildListDelegate(
[YOR_WIDGET()]),
),
);
]

How to preserve the scroll position of tabView when using collapsible app bar (sliverAppBar)?

Problem:
Scroll position of the tabView is not restored correctly when one of the tabView is scrolled to the top (revealing the sliverAppBar). The other tabView will also scrolled to the top (losing its previous scroll position).
This problem will not show up if normal app bar is used (not collapsible app bar)
This problem only shows up when the tabView is scrolled to top
Question:
How to preserve the scroll position of the tabView when using collapsible app bar (sliverAppBar)?
Code:
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new DefaultTabController(
length: 2,
child: Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text('Example'),
pinned: true,
floating: true,
forceElevated: innerBoxIsScrolled,
bottom: TabBar(
tabs: <Widget>[
Tab(text: 'One',),
Tab(text: 'Two'),
],
),
),
];
},
body: TabBarView(
children: <Widget>[
Center(
key: PageStorageKey<String>('one'),
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new ListTile(
title: new Text('One Item $index'),
);
},
),
),
Center(
key: PageStorageKey<String>('two'),
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new ListTile(
title: new Text('Two Item $index'),
);
},
),
),
],
),
),
)
);
}
}
This is actually a known issue and still open. Although there is a workaround as mentioned in this thread:
Here's a workaround that uses
extended_nested_scroll_view
package. With this, I haven't encountered any issues (at least for
now). So until flutter fixes this issue, this workaround seems
sufficient. Only tested on Android.
The basic gist of it is:
Use NestedScrollView from the package extended_nested_scroll_view
Wrap each tab view in a StatefulWidget with AutomaticKeepAliveClientMixin and wantKeepAlive => true
Inside that StatefulWidget(s), wrap the scrollable content in NestedScrollViewInnerScrollPositionKeyWidget
Key values used in innerScrollPositionKeyBuilder and NestedScrollViewInnerScrollPositionKeyWidget must match.

Flutter: Persistent item in CustomScrollView

Currently I'm creating an application using Flutter which involves several lists which can be ordered and filtered. When an ordering or filter is active, persistent bar appears under the app bar which indicates what filters are active. This is achieved by stacking int on top of a ListView using a StackView, and moving the ListView down a little using it's padding. An example of this can be seen in the image below:
Now I'm trying to create a second view using a CustomScrollView and a SliverAppBar, and I want this same "filter bar" behaviour here. I've tried using a SliverList with a single item, and a SliverList below that with the filtered items, but then both lists scroll as if they were one long list. I've also tried adding a bar through the bottom property of the SliverAppBar, but this results in a bar which is placed over the title of the app bar, and as far as I know, there is no way to move this title up. This result can be seen in the image below (the red bar is a placeholder for the filter bar in the first image).
Is there any way to achieve this "persistent" bar effect in a CustomScrollView with a SliverAppBar?
Since there are multiple scrollable views to be managed on the screen, you'll need to use NestedScrollView. This should solve the issue where both scrollable widgets are scrolled like a single long list.
Here's a sample on how it can be implemented similar to the screenshots you've provided.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: MyStatelessWidget(),
);
}
}
class MyStatelessWidget extends StatelessWidget {
MyStatelessWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
// This will help manage the SliverAppBar and ListView
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
flexibleSpace: FlexibleSpaceBar(
background: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/background.jpeg"),
fit: BoxFit.cover,
),
),
child: Container(
padding: EdgeInsets.all(16.0),
alignment: Alignment.centerLeft,
child: Text(
'Title',
style: TextStyle(color: Colors.white, fontSize: 36.0),
),
),
),
),
// title: const Text('Title'),
floating: true,
pinned: true,
expandedHeight: 300.0,
forceElevated: innerBoxIsScrolled,
bottom: AppBar(
backgroundColor: Colors.red,
toolbarHeight: 64.0,
),
),
];
},
body: ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: 30,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
child: Center(child: Text('Item $index')),
);
},
),
),
);
}
}