Is it possible to prevent ModalBottomSheet to hide from outside touch? Like in showDialog() we can use barrierDismissible property to prevent dialog from closing on outside touch
you can use isDismissible: false and enableDrag: false like this
showModalBottomSheet(
isDismissible: false,
enableDrag: false,
builder: (context) {
return Container(
height: 100.0
)
}
);
You need to use showBottomSheet() which doesn't include barrier instead of using showModalBottomSheet().
More info here
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _scaffoldKey = new GlobalKey<ScaffoldState>();
VoidCallback _showPersBottomSheetCallback;
#override
void initState() {
super.initState();
_showPersBottomSheetCallback = _showBottomSheet;
}
void _showBottomSheet() {
setState(() {
_showPersBottomSheetCallback = null;
});
_scaffoldKey.currentState
.showBottomSheet((context) {
return new Container(
color: Colors.greenAccent,
height: 300.0,
child: new Center(
child: new Text("Hi BottomSheet"),
),
);
})
.closed
.whenComplete(() {
if (mounted) {
setState(() {
_showPersBottomSheetCallback = _showBottomSheet;
});
}
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
appBar: new AppBar(
title: new Text("Flutter BottomSheet"),
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {},
child: Padding(
padding: const EdgeInsets.only(top: 10.0),
child: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new RaisedButton(
onPressed: _showPersBottomSheetCallback,
child: new Text("Persistent"),
),
],
),
),
),
),
);
}
}
Try setting isDismissible to false inside showModalBottomSheet
showModalBottomSheet(
isDismissible: false,
context: context,
builder: (BuildContext bc) {
return SheetWidget();
},
);
where SheetWidget is the widget you are trying to call as BottomSheet
Related
In ListView.builder I'm adding a new ListTile with the button Pressed.
Now when I press on ListTile I want to delete that widget.
I have tried to do that by wrapping the widget with InkWell but when I try to delete it deletes from the last ListTile.
How to delete that specific ListTile when I longPressed on that.
Below here is the code
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
/*InkWell(
child: widgets[index],
onLongPress: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Delete?'),
actions: [
IconButton(
onPressed: () {
widgets.removeAt(index);
setState(() {
Navigator.pop(context);
});
},
icon: Icon(Icons.check))
],
));
},
);*/
class _HomeState extends State<Home> {
#override
List<Widget> widgets = [];
int inde = 0;
List<List> blogList = [];
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Note'),
centerTitle: true,
),
body: Column(children: [
Expanded(
child: ListView.builder(
itemCount: widgets.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return InkWell(
child: widgets[index],
onLongPress: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Delete?'),
actions: [
IconButton(
onPressed: () {
widgets.removeAt(index);
setState(() {
Navigator.pop(context);
});
},
icon: Icon(Icons.check))
],
));
},
);
},
),
),
FloatingActionButton(
onPressed: () {
setState(() {
widgets.add(Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(width: 2),
color: Color.fromARGB(255, 76, 178, 204),
),
child: ListTile(
leading: Icon(Icons.circle),
title: TextField(),
)),
));
});
},
child: Icon(Icons.add),
),
]));
}
}
Actually your code works, it deletes the ListTile which you use long press on.
The problem is that you do not assign different controllers to the TextField widgets. So if you enter some text into them, and call setState when deleting one, the values in the TextFields will be wrong, and it looks like the last one is deleted.
So you need to add the following logic to your code:
Create another list like widgets for the controllers.
When adding a new item, create a new controller and assign it to the TextField.
When deleting an item, dispose the controller and remove it from the controllers' list.
Don't forget to dispose all remaining controllers when the widget is disposed.
Here is a sample code, check for the comments where I added to your code. You can run it on DartPad.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: Home(),
),
),
);
}
}
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<Widget> widgets = [];
// this is the list for the controllers
List<TextEditingController> controllers = [];
int inde = 0;
List<List> blogList = [];
// you need to add this in order to dispose
// the controllers when the widget is disposed
#override
void dispose() {
for (var controller in controllers) {
controller.dispose();
}
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Note'),
centerTitle: true,
),
body: Column(children: [
Expanded(
child: ListView.builder(
itemCount: widgets.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return InkWell(
child: widgets[index],
onLongPress: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Delete?'),
actions: [
IconButton(
onPressed: () {
setState(() {
widgets.removeAt(index);
// dispose the controller
controllers[index].dispose();
// remove the controller from list
controllers.removeAt(index);
});
Navigator.pop(context);
},
icon: const Icon(Icons.check))
],
));
},
);
},
),
),
FloatingActionButton(
onPressed: () {
setState(() {
// create a new controller and add it to the list
final newController = TextEditingController();
controllers.add(newController);
widgets.add(Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(width: 2),
color: const Color.fromARGB(255, 76, 178, 204),
),
child: ListTile(
leading: const Icon(Icons.circle),
// assign the controller to the field
title: TextField(controller: newController),
)),
));
});
},
child: const Icon(Icons.add),
),
]));
}
}
I suggest that following the convention, begin all private members of your state class with an underscore, so rename controllers to _controllers etc.
I have an alert dialog that displays a series of check boxes.
I am trying to ensure that if at least one of the checkboxes is selected, the confirm button is enabled, otherwise, if no checkbox is selected, it appears as inactive.
I have a parent and a child widget, both statefull. In one of them I have the button that should be enabled / disabled, and in the other one I have the content of the alert dialog.
The challenge for me has been to notify the parent widget from the child widget, that the flag variable with which I determine whether the button should be active or not, has been updated.
I have tried sending a function to the child widget that it executes, also with ValueSetter and ValueChanged, but so far without success.
If after activating or inactivating one of the checkboxes, I do a hot reload, the button is also updated. So I think it may be something with setState that I am not taking into account.
This is what I have done so far, ready to copy and paste into dartPad.
Thanks for your help.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: FrequencySelectionPage(),
),
),
);
}
}
class FrequencySelectionPage extends StatefulWidget {
FrequencySelectionPage();
#override
_FrequencySelectionPageState createState() => _FrequencySelectionPageState();
}
class _FrequencySelectionPageState extends State<FrequencySelectionPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ListTile(
leading: Icon(Icons.calendar_today),
title: Text('Some days of the week'),
trailing: Icon(Icons.keyboard_arrow_right_rounded),
onTap: () {
_showDialog(context);
}
),),
);
}
void _showDialog(BuildContext context) {
final double screenSize = MediaQuery.of(context).size.height;
bool? canConfirm;
void setCanConfirm(bool value) {
setState(() {
canConfirm = value;
});
}
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Choose days"),
content: Container(
width: 200,
height: screenSize * 0.60,
child: ShowAlertContent(
setCanConfirm: setCanConfirm),
),
actions: <Widget>[
SizedBox(
width: screenSize * 0.50,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Cancel'),
),
SizedBox(
height: 20.0,
width: 20.0,
),
ElevatedButton(
child: Text('Confirm'),
onPressed: (canConfirm == false)
? null
: () {
Navigator.of(context).pop();
},
),
],
),
)
],
);
},
);
}
}
class ShowAlertContent extends StatelessWidget {
final ValueSetter<bool> setCanConfirm;
const ShowAlertContent(
{required this.setCanConfirm});
#override
Widget build(BuildContext context) {
return ShowSomeWeekDaysOptionContent(setCanConfirm: setCanConfirm);
}
}
class ShowSomeWeekDaysOptionContent extends StatefulWidget {
final ValueChanged<bool> setCanConfirm;
const ShowSomeWeekDaysOptionContent({required this.setCanConfirm});
#override
_ShowSomeWeekDaysOptionContentState createState() =>
_ShowSomeWeekDaysOptionContentState();
}
class _ShowSomeWeekDaysOptionContentState
extends State<ShowSomeWeekDaysOptionContent> {
Map<String, bool> days = {
'Day1': false,
'Day2': false,
'Day3': false,
'Day4': false,
'Day5': false,
'Day6': false,
'Day7': false
};
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: ListView(
padding: EdgeInsets.all(8.0),
children: days.keys.map(
(day) {
return StatefulBuilder(builder:
(BuildContext context, StateSetter setCheckboxState) {
return CheckboxListTile(
title: Text(day),
value: days[day],
onChanged: (bool? value) {
setState(() {});
setCheckboxState(() {
days[day] = value!;
if (days.containsValue(true)) {
widget.setCanConfirm(true);
} else {
widget.setCanConfirm(false);
}
});
},
);
});
},
).toList(),
),
),
],
);
}
}
In your example you need something which rebuilds the button, when the value of canConfirm changes. You could use a ValueListenableBuilder. Therefore you have to make canConfirm a ValueNotifier.
Here is the working example:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: FrequencySelectionPage(),
),
),
);
}
}
class FrequencySelectionPage extends StatefulWidget {
FrequencySelectionPage();
#override
_FrequencySelectionPageState createState() => _FrequencySelectionPageState();
}
class _FrequencySelectionPageState extends State<FrequencySelectionPage> {
late ValueNotifier<bool> canConfirm;
#override
void initState() {
canConfirm = ValueNotifier(false);
super.initState();
}
void setCanConfirm(bool value) {
canConfirm.value = value;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ListTile(
leading: Icon(Icons.calendar_today),
title: Text('Some days of the week'),
trailing: Icon(Icons.keyboard_arrow_right_rounded),
onTap: () {
_showDialog(context);
}),
),
);
}
void _showDialog(BuildContext context) {
final double screenSize = MediaQuery.of(context).size.height;
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Choose days"),
content: Container(
width: 200,
height: screenSize * 0.60,
child: ShowAlertContent(setCanConfirm: setCanConfirm),
),
actions: <Widget>[
SizedBox(
width: screenSize * 0.50,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Cancel'),
),
SizedBox(
height: 20.0,
width: 20.0,
),
ValueListenableBuilder<bool>(
valueListenable: canConfirm,
builder: (context, value, child) {
return ElevatedButton(
child: Text('Confirm'),
onPressed: (value == false)
? null
: () {
Navigator.of(context).pop();
},
);
},
),
],
),
)
],
);
},
);
}
}
class ShowAlertContent extends StatelessWidget {
final ValueSetter<bool> setCanConfirm;
const ShowAlertContent({required this.setCanConfirm});
#override
Widget build(BuildContext context) {
return ShowSomeWeekDaysOptionContent(setCanConfirm: setCanConfirm);
}
}
class ShowSomeWeekDaysOptionContent extends StatefulWidget {
final ValueChanged<bool> setCanConfirm;
const ShowSomeWeekDaysOptionContent({required this.setCanConfirm});
#override
_ShowSomeWeekDaysOptionContentState createState() =>
_ShowSomeWeekDaysOptionContentState();
}
class _ShowSomeWeekDaysOptionContentState
extends State<ShowSomeWeekDaysOptionContent> {
Map<String, bool> days = {
'Day1': false,
'Day2': false,
'Day3': false,
'Day4': false,
'Day5': false,
'Day6': false,
'Day7': false
};
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: ListView(
padding: EdgeInsets.all(8.0),
children: days.keys.map(
(day) {
return StatefulBuilder(builder:
(BuildContext context, StateSetter setCheckboxState) {
return CheckboxListTile(
title: Text(day),
value: days[day],
onChanged: (bool? value) {
setCheckboxState(() {
days[day] = value!;
if (days.containsValue(true)) {
widget.setCanConfirm(true);
} else {
widget.setCanConfirm(false);
}
});
},
);
});
},
).toList(),
),
),
],
);
}
}
I don’t know about your case but ummmm.. I think this one maybe a lot easier
`bool _isChecked = false;
#override
Widget build(BuildContext context) {
return Column(
children: [
Checkbox(
value: _isChecked,
onChanged: (value) {
setState(() {
_isChecked = value;
});
},
),
ElevatedButton(
child: Text('Button'),
onPressed: (){
if(_isChecked){
print('CHeckbox is checked');
}else{
print('CHeckbox is not checked');
}
},
),
],
);
}`
I made two forms with pass fields on both, then made all the code to, when the user clicks in the eye Icon, the field show the password, clicking again it hide the password.
But now I put these forms inside an Alert Dialog widget and now it doesn't updating when I click in the icon, only updates if I close the dialog and open again (you open the dialog, click in the icon, it doesn't change. If you close and open again you see the icon changed)
After some search I tried Stateful Builder but it doesn't work too.
Dialog:
Future<void> _myDialog(child){
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return SingleChildScrollView(
child: AlertDialog(
content: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Padding(
padding: EdgeInsets.all(20),
child: child,
);
},
),
insetPadding: EdgeInsets.only(left: 10, right: 10),
),
);
}
);
}
Toggle method referenced in my textFields:
void _toggle(int index) {
setState(() {
_toggleList[index] = !_toggleList[index];
});
}
How can I toggle it instantly when the user click in the icon as outside the alert?
Edit
Row _showButtons(){
return Row(
children: [
RaisedButton(
child: Text("Change email"),
onPressed: () {_myDialog(_showEmailFields());}
),
RaisedButton(
child: Text("Change pass"),
onPressed: () {_myDialog(_showPassFields());}
),
],
);
}
I have created a structure for you that you should use for achieving what you want here. Make your forms into a separate stateful widgets, so that they have their own State, and you call the right setState function. Right now the setState function you are calling does not belongs to the state of your alert dialog.
class Test extends StatefulWidget {
#override
State<StatefulWidget> createState() => _TestState();
}
class _TestState extends State<Test> {
void showForm() {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Login"),
content: LoginWidget(),
);
},
);
}
#override
Widget build(BuildContext context) {
TextTheme textTheme = Theme.of(context).textTheme;
return Scaffold(
appBar: AppBar(
title: Text("Appbar"),
),
body: Center(
child: RaisedButton(
child: Text("Show Form"),
onPressed: showForm,
),
),
);
}
}
class LoginWidget extends StatefulWidget {
LoginWidget({Key key}) : super(key: key);
#override
LoginWidgetState createState() => LoginWidgetState();
}
class LoginWidgetState extends State<LoginWidget> {
GlobalKey<FormState> _formKey;
bool _passwordVisible;
#override
void initState() {
super.initState();
_formKey = GlobalKey<FormState>();
_passwordVisible = false;
}
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: "Email"),
),
SizedBox(
height: 10,
),
TextFormField(
obscureText: !_passwordVisible,
decoration: InputDecoration(
labelText: "Password",
suffixIcon: IconButton(
onPressed: () {
setState(() {
_passwordVisible = !_passwordVisible;
});
},
icon: Icon(
_passwordVisible ? Icons.visibility : Icons.visibility_off),
),
),
),
],
),
);
}
}
Here I am using provider package for state management.
I have a SpeedDial widget in the floatingActionButton. And whenever I add something in the list mainGoalList by using speedDial and do Navigator.pop(context); it does go back to the page but does not update the list.
SpeedDial
SpeedDialChild(
child: Icon(Icons.book),
backgroundColor: Colors.blue,
label: 'Add Notes',
labelStyle: TextStyle(
fontSize: 18.0,
color: Colors.black,
),
onTap: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context)
.viewInsets
.bottom),
child: AddNotes(),
),
));
}),
AddNote
Center(
child: FlatButton(
onPressed: () {
if (_actcontroller.text == null) {
print("Cannot add null topic");
} else {
addingTheNotes();
Navigator.pop(context);
}
},
child: Text("Add"),
color: Colors.blue,
),
)
Adding the notes
addingTheNotes() {
theDataProvider.ourAllnotes.add(
TodaysNoteClass(
note: _actcontroller.text,
dateTime: theDataProvider.notesChoosenDate,
status: false,
),
);
theDataProvider.showingTheTodaysList();
}
Here is the change notifier
List<TodaysNoteClass> _ourAllnotes = [];
List<TodaysNoteClass> get ourAllnotes => _ourAllnotes;
set ourAllnotes(List<TodaysNoteClass> val) {
_ourAllnotes = val;
notifyListeners();
}
Consumer class, this is where I am showing the notes
class HomePage extends StatefulWidget {
static const String id = 'homePage';
final String todaysDate =
DateFormat('d MMMM').format(DateTime.now()).toLowerCase();
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
var theDataProvider;
Widget build(BuildContext context) {
theDataProvider = Provider.of<TheData>(context, listen: false);
return Consumer<TheData>(
builder: (context, value, child) => SingleChildScrollView(
child: Container(
child: Column(
children: [
Container(
height: 120,
child: TodaysNote(),
),
],
),
),
),
);
}
}
And this is the TodaysNote class
class TodaysNote extends StatefulWidget {
TodaysNote({Key key}) : super(key: key);
bool boxChecked = false;
#override
_TodaysNoteState createState() => _TodaysNoteState();
}
class _TodaysNoteState extends State<TodaysNote> {
var theDataProvider;
Widget build(BuildContext context) {
theDataProvider = Provider.of<TheData>(context, listen: false);
return Consumer<TheData>(
builder: (context, value, child) => Container(
child: theDataProvider.showingTheTodaysList(),
),
);
}
}
But now when I go to another screen and then come to the previous screen. I see the updated list.
I have wrapped the main file with provider, wrapped the files with consumer but did not work.
What might be the reason behind this?
try using this:
Navigator.push( context, MaterialPageRoute( builder: (context) => SecondPage()), ).then((value) => setState(() {}));
I want to Create an TextField at the bottom of the page like message app.
There is also a IconButton, which adds the entered text into ListView if TextField is not empty. If it is empty then it will show error in SnackBar.
The Problem is the SnackBar stacks on top of TextField. But I want it to be either top or bottom of TextField.
import 'package:flutter/material.dart';
Future<void> main() async {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MainPage(),
);
}
}
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
final _textList = <String>[];
TextEditingController _textController;
bool _addText(context, String text) {
print(text);
if (text?.isNotEmpty == true) {
setState(() {
_textList.add(text);
});
return true;
} else {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text("Invalid Text Entered"),
behavior: SnackBarBehavior.fixed,
),
);
return false;
}
}
#override
void initState() {
_textController = TextEditingController();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: ListView.separated(
itemCount: _textList.length,
separatorBuilder: (_, __) => Divider(height: 1.0),
itemBuilder: (context, index) => ListTile(
title: Text("${_textList[index]}"),
),
),
),
_buildBottom(),
],
),
),
);
}
Widget _buildBottom() {
return Material(
elevation: 5.0,
color: Colors.blue[100],
child: Row(
children: <Widget>[
Expanded(
child: TextField(
controller: _textController,
decoration: InputDecoration(
hintText: "Enter Text",
contentPadding: EdgeInsets.symmetric(horizontal: 10.0),
border: InputBorder.none,
),
),
),
Builder(
builder: (context) => IconButton(
icon: Icon(Icons.add),
onPressed: () {
final success = _addText(context, _textController.text);
if (success) _textController.clear();
},
),
),
],
),
);
}
}
This is my code in DartPad
try this,
import 'package:flutter/material.dart';
Future<void> main() async {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MainPage(),
);
}
}
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
final _textList = <String>[];
TextEditingController _textController;
bool isVisible = false;
bool _addText(context, String text) {
print(text);
if (text?.isNotEmpty == true) {
setState(() {
_textList.add(text);
});
return true;
} else {
Scaffold.of(context).showSnackBar(
new SnackBar(
content: Text("Invalid Text Entered"),
behavior: SnackBarBehavior.fixed,
duration: Duration(seconds: 3),
onVisible: (() {
setState(() {
isVisible = true;
});
Future.delayed(Duration(seconds: 3)).then((_) => setState(() {
isVisible = false;
}));
}),
),
);
return false;
}
}
#override
void initState() {
_textController = TextEditingController();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: ListView.separated(
itemCount: _textList.length,
separatorBuilder: (_, __) => Divider(height: 1.0),
itemBuilder: (context, index) => ListTile(
title: Text("${_textList[index]}"),
),
),
),
AnimatedContainer(
margin: EdgeInsets.only(bottom: isVisible ? 50 : 0),
child: _buildBottom(),
duration: Duration(milliseconds: 100),
),
],
),
),
);
}
Widget _buildBottom() {
return Material(
elevation: 5.0,
color: Colors.blue[100],
child: Row(
children: <Widget>[
Expanded(
child: TextField(
controller: _textController,
decoration: InputDecoration(
hintText: "Enter Text",
contentPadding: EdgeInsets.symmetric(horizontal: 10.0),
border: InputBorder.none,
),
),
),
Builder(
builder: (context) => IconButton(
icon: Icon(Icons.add),
onPressed: () {
final success = _addText(context, _textController.text);
if (success) _textController.clear();
},
),
),
],
),
);
}
}
Perhaps using Flushbar might help with your problem. There are many properties that you can change, such as flushbarPosition.
It might not solve your problem exactly how you would expect it to but it can make the Flushbar appear from the top instead of the bottom and that's one way around your problem
Flushbar: https://pub.dev/packages/flushbar
I think the best thing you can do here is to change the behaviour to floating
SnackBar(
behavior: SnackBarBehavior.floating,
...