showModalBottomsheet adds listview as a child Widget. When listview slides to the top, how to respond to the bottom sheet drop-down gesture by continuing to pull down
showModalBottomSheet(
context: context,
isScrollControlled: true,
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.85),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
topLeft: Radius.circular(20)),
),
builder: (context) {
return ListView.builder(
controller: scrollController,
itemBuilder: (context, index) => ListTile(
title: Text(index.toString()),
onTap: () => Navigator.pop(context),
));
});
You can use DraggableScrollableSheet
showModalBottomSheet(
context: context,
isScrollControlled: true,
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.85),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(20), topLeft: Radius.circular(20)),
),
builder: (context) {
return DraggableScrollableSheet(
builder: (context, scrollController) {
return ListView.builder(
itemCount: 32,
controller: scrollController,
itemBuilder: (context, index) => ListTile(
title: Text(index.toString()),
onTap: () => Navigator.pop(context),
),
);
},
);
},
);
Find more about DraggableScrollableSheet decoration
Related
To implement flutter bottomSheetDialog with dynamic height, I wrote a code like this.
void showCustomBottomSheetDialog(Widget body, BuildContext context) {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (BuildContext ctx) {
return Wrap(
children: [
Column(
children: [
Container(
height: 24.sp,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
topRight: Radius.circular(10.0),
),
),
),
body,
],
),
],
);
},
);
}
showCustomBottomSheetDialog(
Container(
child: Column(
children: [
TextFormField(),
Text('asdfasdfds'),
Text('asdfasdfds'),
Text('asdfasdfds'),
],
),
),
context,
);
But with this code, the displayed bottomSheet did not have a rounded corner...
Could you tell me what is a problem of my code...?
create rounded corner manually
eg:
showModalBottomSheet(
isScrollControlled: true,
context: context,
backgroundColor: Colors.transparent,
builder: (contex) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
const BorderRadius.vertical(top: Radius.circular(18))),
child: Column(
children: []
....
also you can wrap it with DraggableScrollableSheet to make it scrollable widget
This is because the Container with rounded corner is inside the Column widget.
For this to work ,lift up the Container.
Code now:
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (BuildContext ctx) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
topRight: Radius.circular(10.0),
),
),
child: Column(...)
),
},
);
Actually, we have shape property on showModalBottomSheet and can be used to make rounded corner, like
showModalBottomSheet(
isScrollControlled: true,
context: context,
shape: const RoundedRectangleBorder( //this
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
),
),
More about showModalBottomSheet
for a while now, I was trying to learn Flutter for mobile development. So, everything is straight forward and easy to grasp.
But, the following issues I cannot seem to solve:
Resizing the CircleAvatar() in the AppBar: I tried using scale, size, nothing worked.
Whatever I added after the 1st ListView.builder(), the emulator does not read/ display
my flutter is up-to-date and no errors/issues are shown when I run flutter doctor or my run the app.
Thanks
Code Used:
class MessageScreen extends StatefulWidget {
static Route<dynamic> route() => MaterialPageRoute(
builder: (context) => MessageScreen(),
);
#override
_MessageScreenState createState() => _MessageScreenState();
}
class _MessageScreenState extends State<MessageScreen> {
String tempLink =
'https://images.unsplash.com/photo-1599566150163-29194dcaad36?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80';
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue[400],
appBar: AppBar(
elevation: 0.0,
leading: CircleAvatar(
backgroundImage: NetworkImage(tempLink),
radius: 15.0,
child: tempLink == null ? Text('HH') : null,
),
title: Text('Chats'),
backgroundColor: Colors.blue[400],
actions: [
IconButton(
onPressed: () {},
icon: Icon(Icons.search),
),
],
),
body: Column(
children: [
Row(
children: [
Container(
child: ListView.builder(
itemCount: newMatching.length,
padding: EdgeInsets.only(left: 6),
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ChatScreen(
user: newMatching[index],
),
),
),
child: _profileButton(tempLink),
);
},
),
),
],
),
SizedBox(
height: 18,
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20), topRight: Radius.circular(20)),
),
child: ListView.builder(
itemCount: chats.length,
itemBuilder: (BuildContext context, int index) {
final Message chat = chats[index];
return GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ChatScreen(
user: chat.sender,
),
),
),
child: Container(
margin: EdgeInsets.only(top: 5, bottom: 5, right: 1),
padding:
EdgeInsets.symmetric(horizontal: 2, vertical: 5),
decoration: BoxDecoration(
color: chat.unread ? Color(0xFFFFEFEE) : Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(20.0),
bottomRight: Radius.circular(20.0),
),
),
child: _chatNavigatorButton(
chat.sender.imgAvatar,
chat.sender.fname,
chat.text,
chat.time,
chat.unread)),
);
}),
),
],
),
);
}
}
Try wrapping the CircleAvatar with a Container:
Container(height: 10, width: 10, child: CircleAvatar(...))
Is there a chance that chats simply has the length of 0 and no elements? Maybe the second ListView.builder() does display correctly but includes no items. At least that's what I can retrieve from the given code.
I have an issue with modal bottom sheet.
After I use Navigator.push to another page, the modal bottom sheet remain there when I go back.
I already try using FocusScope.of(context).focusedChild.unfocus(); and Navigator.pop(context); still not helping.
Modal bottom sheet code:
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blueAccent,
child: Icon(
Icons.add,
color: Colors.white,
),
onPressed: () {
showModalBottomSheet(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
context: context,
isScrollControlled: true,
builder: (context) => SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: AddTask(), //open statefull widget
),
),
);
}),
Add Task code:
Row(
children: <Widget>[
InkWell(
borderRadius: BorderRadius.circular(8),
onTap: () async {
FocusScope.of(context).focusedChild.unfocus();
await DatabaseService(uid: user.uid, taskId: taskId)
.updateTask(false, _titleValue, _notesValue,
UpdateChecklist().checklistInput, '', '', '');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TaskDetail(
uid: user.uid,
taskId: taskId,
)),
);
},
child: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
border: Border.all(color: Colors.blueAccent),
borderRadius: BorderRadius.circular(8)),
child: Icon(
Icons.add,
color: Colors.blueAccent,
),
),
),
is there any way to make the modal bottom sheet go back to unfocus when I return to the page?
it solved by adding then.
Row(
children: <Widget>[
InkWell(
borderRadius: BorderRadius.circular(8),
onTap: () async {
await DatabaseService(uid: user.uid, taskId: taskId)
.updateTask(false, _titleValue, _notesValue,
UpdateChecklist().checklistInput, '', '', '');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TaskDetail(
uid: user.uid,
taskId: taskId,
)),
).then((value) => Navigator.pop(context));
closing showModalBottomSheet programmatically is done via
Navigator.pop(context);
I'm using openContainer to animate the transition of the FAB to a view/screen - however, there seems to be a box around the fab. How do I remove this ?
OpenContainer(
transitionDuration: Duration(milliseconds: 1000),
closedBuilder: (BuildContext c, VoidCallback action) =>
FloatingActionButton(
elevation: 10,
backgroundColor: Colors.pink,
onPressed: () {
action();
},
child: Icon(Icons.add),
),
openBuilder: (BuildContext c, VoidCallback action) {
return MyScreen();
},
tappable: false,
));
I got the same problem and found the solution. This is an alternative to removing the box - following the example from the animation github repo:
Replace FloatingActionButton with SizedBox containing a height and width
Include closedElevation property in OpenContainer to maintain the elevation effect
Include closedShape property in OpenContainer to make SizedBox round
OpenContainer(
transitionDuration: Duration(milliseconds: 1000),
closedColor: Colors.pink,
closedBuilder: (BuildContext c, VoidCallback action){
return SizedBox(
height: 56,
width: 56,
child: Center(
child: Icon(
Icons.add,
color: Colors.white,
),
),
);
}
openBuilder: (BuildContext c, VoidCallback action) {
return MyScreen();
},
tappable: false,
closedElevation: 6.0,
closedShape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(56 / 2),
),
),
);
try this and it's done
floatingActionButton: OpenContainer(
closedColor: Colors.blue,
closedShape: const CircleBorder(),
closedElevation: 6,
transitionDuration: Duration(seconds: 3),
closedBuilder: (BuildContext c, openWidget) {
return FloatingActionButton(
elevation: 0,
onPressed: openWidget,
child: Icon(Icons.add),
);
},
openBuilder: (BuildContext c, VoidCallback action) => SomeNewPage(),
),
solved liked that
closedColor: Colors.transparent,
closedElevation: 12,
closedShape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30),),
openColor: Colors.transparent,
openElevation: 0,
I want to implement the modal bottom sheet with a webview as a child in it. When I try to do it, the webview gets messed up and the sheet comes on the top of the screen instead of the bottom.
I tried to change the height but nothing really worked.
Pub dependency: flutter_webview_plugin: ^0.3.5
void _showModelSheet() {
showModalBottomSheet(
context: context,
builder: (builder) {
return new Container(
height: screenHeight / 4,
child: new Container(
decoration: new BoxDecoration(
color: Colors.amber,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(20.0),
topRight: const Radius.circular(20.0))),
child: Container(
child: new MaterialApp(
debugShowCheckedModeBanner: false,
routes: {
"/": (_) => new WebviewScaffold(
url: "https://www.google.com",
),
},
),
),
),
);
});
}
child: RaisedButton(
elevation: 10,
splashColor: Colors.black,
color: Colors.red.shade900.withOpacity(0.7),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(110)),
onPressed: _showModelSheet,
child: Text(
"sheet"),
),
),
I want to make the whole webview to get wrap into the height of the modal bottom sheet.
You are returning a MaterialApp inside another. And the reason is that the plugin you're using forces you to do that.
Better use the oficial Flutter WebView plugin.
webview_flutter: ^0.3.9+1
Then use it like this:
void _showModelSheet() {
showModalBottomSheet(
context: context,
builder: (builder) {
return new Container(
height: MediaQuery.of(context).size.height / 4,
child: new Container(
decoration: new BoxDecoration(color: Colors.amber, borderRadius: new BorderRadius.only(topLeft: const Radius.circular(20.0), topRight: const Radius.circular(20.0))),
child: Container(
child: WebView(
initialUrl: 'https://google.com',
)),
),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
elevation: 10,
splashColor: Colors.black,
color: Colors.red.shade900.withOpacity(0.7),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(110)),
onPressed: _showModelSheet,
child: Text("sheet"),
),
),
);
}
This is the result: