I want to create bottom sheet like Instagram post sharing page
everything work fine but I need to start flexibleSpace animation before DraggableScrollableSheet at the maxChildSize property and finished at maxChildSize
Stack(
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
Navigator.of(cotext).pop()
},
child: Container(
width: context.width,
height: context.height,
),
),
SizedBox.fromSize(
size: Size.fromHeight(context.height),
child: DraggableScrollableSheet(
minChildSize: 0.5,
maxChildSize: 1,
initialChildSize: 0.5,
builder: (context, scroll) {
return SafeArea(
child: Container(
color: Colors.white,
child: CustomScrollView(
controller: scroll,
slivers: [
SliverAppBar(
pinned: true,
title:title,
),
SliverList(
delegate:
SliverChildBuilderDelegate((context, index) {
return Object()
}, childCount: 100))
],
),
),
);
},
),
),
],
);
Related
I am trying to put a listView inside ModalBottomSheet in flutter and I want there to be a divider in the top of the ModalBottomSheet that doesn't move when the listView moves. And I keep getting an error
here is what I am trying to do:
ModalBottomSheet(
-Container(), // which shouldn't scroll
-ListView(), // should scroll
)
tried:
to make ModalBottomSheet.isScrollControlled = false
BottomModalSheet
Widget _showModalBottomSheet() => DraggableScrollableSheet(
expand: false,
key: UniqueKey(),
initialChildSize: 0.7,
maxChildSize: 0.9,
minChildSize: .5,
builder: (context, controller) => Column(
children: [
Container(
height: 59,
color: Colors.cyanAccent,
),
Expanded(
child: ListView(
controller: controller,
children: [
...List.generate(
40,
(index) => Container(
height: 100,
color:
index.isEven ? Colors.deepOrange : Colors.deepPurple,
),
)
],
),
),
],
),
);
And Use
await showModalBottomSheet(
isScrollControlled: true,
isDismissible: true,
backgroundColor: Colors.transparent,
context: context,
builder: (context) => _showModalBottomSheet(),
);
I am trying to make silver app bar,but stuck in a problem. I have used infitelist to build a list as i found infitelist handle the list view more niecly , due to which app bar won't go on top as shown in blow gif. As infite list is not supported i have wrapped it with container.
Below is the code
SliverList(
delegate: SliverChildListDelegate(
<Widget>[
Container(
height: 500,
child: Column(
children: [
TopListView(posts: state.posts),
Expanded(
child: InfiniteList(
loadingBuilder: (context) {
return const SizedBox(
height: 100,
child: LoadingIndicator(
message: 'Fetching older posts',
),
);
},
hasError: state.status.isFailure,
isLoading: state.status.isLoading,
itemCount: state.posts.length,
hasReachedMax: state.hasReachedMax,
onFetchData: () {
context.read<PostsBloc>().add(const PostsRequested());
},
itemBuilder: (context, index) {
final post = state.posts[index];
return PostCard(post: post);
},
errorBuilder: (context) {
return SizedBox(
height: 100,
child: Center(
child: ReloadButton(
onPressed: () {
context
.read<PostsBloc>()
.add(const PostsRequested());
},
message: 'Failed to fetch more posts',
),
),
);
},
emptyBuilder: (context) {
return Center(
child: ReloadButton(
onPressed: () {
context
.read<PostsBloc>()
.add(const PostsRequested());
},
message: 'No Posts Found',
),
);
},
),
),
],
),
)
],
),
)
How can we solve this?
You can use SingleChildScrollView instead of Container.
Actually, all you need is CustomScrollView and SliverAppBar.
here is a widget example:
Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
pinned: false,
snap: true,
floating: true,
expandedHeight: 160.0,
flexibleSpace: const FlexibleSpaceBar(
title: Text('SliverAppBar'),
background: FlutterLogo(),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: index.isOdd ? Colors.white : Colors.black12,
height: 100.0,
child: Center(
child: Text('$index', textScaleFactor: 5),
),
);
},
childCount: 20,
),
),
],
),
);
If you want to know more this is SliverAppBar docs
What I would like to do
I want to make it possible for the user to drag the blue area up with their finger.
Problem
cant drag up draggable
Architecture
NestedScrollView (
headerSliver:SliverAppBar(...)
body: Stack(
childern: [
Expanded(
child: SliverGrid(),
),
Draggable(),
],
),
),
What I checked
I confirmed that the touch works on the draggable. I made an InkWell with a builder and confirmed that the onPressed function works.
I tried with CustomScrollView as well, but it still didn't work.
code
NestedScrollView
NestedScrollView(
headerSliverBuilder: (context, innerBoxScrolled) {
return [
SliverAppBar(
leading: null,
elevation: 0,
expandedHeight: 160,
pinned: false,
flexibleSpace: TopNavBar(
height: 100,
),
bottom: AppBar(
leading: null,
toolbarHeight: 100,
elevation: 0,
actions: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AdTopTabBar(),
FilterBar(),
],
),
],
),
),
];
},
body: Stack(
children: [
Expanded(
child: HomeAdCollection(),
),
MyAdDraggable(),
],
),
),
Draggable
class MyAdDraggable extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DraggableScrollableSheet(
key: key,
initialChildSize: 0.05,
minChildSize: 0.05,
maxChildSize: 0.7,
expand: true,
builder: (context, scrollcontroller) {
return InkWell(
onTap: () {
print('ff');
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
color: Colors.blue[100],
),
),
);
},
);
}
}
There must be at least one child in the DraggableScrollableSheet that uses scrolling. Otherwise, you can't drag it up.
When I put ListView as a child in DraggableScrollableSheet, it works well!
The glow acts like the entire screen is a list. There some way that I can put the glow below the appbar? (edit: without losing the floating effect of the appbar)
CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('Home Scree'),
floating: true,
leading: Icon(Icons.alarm),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, i) {
return Column(
children: <Widget>[
ProductCard(),
Divider(
height: 0,
thickness: 1,
),
],
);
},
childCount: 10,
),
),
],
),
Maybe you can try to use NestedScrollView,like this:
#override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [SliverAppBar(
leading: Icon(Icons.alarm),
title: Text('Home Scree'),
expandedHeight: kToolbarHeight,
floating: true,
)];
},
body: ListView.builder(
padding: EdgeInsets.zero,
itemCount: 10,
itemBuilder: (context, index) {
return Column(
children: <Widget>[
ProductCard(),
Divider(
height: 0,
thickness: 1,
),
],
);
}),
),
);
}
I'm using a Flutter modal bottom sheet to display some options for the user to select.
I have a Column with a list of ListTiles as the content of the bottom sheet.
My problem is that if I have more than 6 ListTiles, some are cut off and not displayed.
Is there a way to make the bottom Sheet scrollable?
Just change your Column into a ListView, like so:
return ListView(
children: <Widget>[
...
]
);
What if I don't want the content of the sheet to be scrolled, but the sheet itself?
If you want the user to be able to swipe up the bottom sheet to fill the screen, I'm afraid this isn't possible in the current implementation of the modular bottom sheet.
I've found a solution implementing the code below
void _showBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) {
return GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
color: Color.fromRGBO(0, 0, 0, 0.001),
child: GestureDetector(
onTap: () {},
child: DraggableScrollableSheet(
initialChildSize: 0.4,
minChildSize: 0.2,
maxChildSize: 0.75,
builder: (_, controller) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(25.0),
topRight: const Radius.circular(25.0),
),
),
child: Column(
children: [
Icon(
Icons.remove,
color: Colors.grey[600],
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: 100,
itemBuilder: (_, index) {
return Card(
child: Padding(
padding: EdgeInsets.all(8),
child: Text("Element at index($index)"),
),
);
},
),
),
],
),
);
},
),
),
),
);
},
);
}
If you want a model bottom sheet that can be scrolled.
You can use the isScrollControlled attribute of showModalBottomSheet to achieve the effect.
If you want a persistent bottom sheet that can be scrolled.
You can use the DraggableScrollableSheet
Example:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DraggableScrollableSheet'),
),
body: SizedBox.expand(
child: DraggableScrollableSheet(
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
),
),
);
}
}
Here is the official video from the Flutter team.
A live demo on DartPad can be found here.
Almost the same solution like this one but without the unnecessary layers of gesture detectors etc.
The important part is the expand: false, in DraggableScrollableSheet, because it defaults to true. This causes the bottom sheet to expand to full height in default config. With this set to false there is no need to wrap the bottom sheet with two gesture detectors to detect the outside tap.
Also in this case only one shape is required.
showModalBottomSheet(
context: context,
isScrollControlled: true,
isDismissible: true,
shape: const RoundedRectangleBorder(
borderRadius:
BorderRadius.vertical(top: Radius.circular(16))),
builder: (context) => DraggableScrollableSheet(
initialChildSize: 0.4,
minChildSize: 0.2,
maxChildSize: 0.75,
expand: false,
builder: (_, controller) => Column(
children: [
Icon(
Icons.remove,
color: Colors.grey[600],
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: 100,
itemBuilder: (_, index) {
return Card(
child: Padding(
padding: EdgeInsets.all(8),
child: Text("Element at index($index)"),
),
);
},
),
),
],
),
),
);