How can i set maximum size for an alert dialog in flutter and the same dialog shrink if the items are not upto the maximum size here is the code am currently using
showDialog(
context: context,
builder: (ctx) => StatefulBuilder(builder: (context, setState) {
return AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0))),
content: Wrap(
children: [
Container(
padding: const EdgeInsets.all(5),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height / 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Select Country'),
const SizedBox(height: 10),
Expanded(
child: ListView.builder(
itemCount: getCountries().length,
itemBuilder: (BuildContext context, int index) {
final User us = getCountries()[index];
return InkWell(
onTap: () {
Navigator.pop(context);
setState(() {
countryId = us.id;
});
},
child: Container(
margin: const EdgeInsets.only(
left: 0, top: 5, right: 0, bottom: 5),
padding: const EdgeInsets.all(10),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(10))),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Text(us.name,
style: TextStyle(
color: AppColor.colorAppGreen,
fontSize: 16)),
],
),
),
);
},
),
)
],
),
),
],
),
);
}));
I need the alert dialog to shrink to fit if the items are small but increase to the maximum height with more items which is half of the screen with the code above am able to set the maximum height with this
height: MediaQuery.of(context).size.height / 2,
but when the items are few i get a lot of empty spaces. Any help will be greatly appreciated.
try this:
showDialog(
context: context,
builder: (ctx) =>
StatefulBuilder(builder: (context, setState) {
return AlertDialog(
insetPadding: EdgeInsets.zero,
shape: const RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(10.0))),
title: const Text('Select Country'),
content: Container(
padding: const EdgeInsets.all(5),
width: MediaQuery.of(context).size.width,
// height: MediaQuery.of(context).size.height,
child: ListView.builder(
shrinkWrap: true,
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
// final User us = getCountries()[index];
return InkWell(
onTap: () {
Navigator.pop(context);
// setState(() {
// countryId = us.id;
// });
},
child: Container(
margin: const EdgeInsets.only(
left: 0, top: 5, right: 0, bottom: 5),
padding: const EdgeInsets.all(10),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(10))),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Text('us.name',
style: TextStyle(
color: Colors.green,
fontSize: 16)),
],
),
),
);
},
)),
);
}));
Note: I set dialog's insetPadding to zero, to get max size.Fill free to play with that to get your prefer look.
Related
I am trying to get my Flutter Dialog to show page indicator dots based off the onPageChanged setState and it doesnt seem to be working. What is happening is the dots are appearing and one is highlighted but as I swipe the dots are not following the current page. Any ideas? When I add a print statement to my setState I can see the activePage is corresponding with the current index. I am at odds as to why this is not working?
Future openDialog() => showDialog(
context: context,
builder: (BuildContext context) => Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
backgroundColor: const Color(0xFF64748b),
child: Container(
height: 300.0, // Change as per your requirement
width: 300.0, // Change as per your requirement
child: Column(
children: [
SizedBox(
width: MediaQuery.of(context).size.width,
height: 200,
child: PageView.builder(
scrollDirection: Axis.horizontal,
pageSnapping: true,
itemCount: eqs.length,
controller: _pageController,
onPageChanged: (page) {
setState(() {
activePage = page;
// print(activePage);
});
},
itemBuilder: (context, index) {
final titles = eqs[index];
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(15.0),
child: Text(
titles.eqTitle,
style: const TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: Math.tex(
titles.eq,
mathStyle: MathStyle.display,
textStyle: const TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.bold,
),
),
),
],
);
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: indicators(eqs.length, activePage))
],
),
),
));
List<Widget> indicators(eqsLength, currentIndex) {
return List<Widget>.generate(eqsLength, (index) {
return Container(
margin: const EdgeInsets.all(5.0),
width: 10,
height: 10,
decoration: BoxDecoration(
color: currentIndex == index ? Colors.greenAccent : Colors.black26,
shape: BoxShape.circle),
);
});
}
Hey if you're trying to have a page indicator at the bottom of your page view, you can just use a very simple package called smooth_page_indicator
Future openDialog() => showDialog(
context: context,
builder: (BuildContext context) => Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
backgroundColor: const Color(0xFF64748b),
child: Container(
height: 300.0, // Change as per your requirement
width: 300.0, // Change as per your requirement
child: Column(
children: [
SizedBox(
width: MediaQuery.of(context).size.width,
height: 200,
child: PageView.builder(
scrollDirection: Axis.horizontal,
pageSnapping: true,
itemCount: eqs.length,
controller: _pageController,
itemBuilder: (context, index) {
final titles = eqs[index];
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(15.0),
child: Text(
titles.eqTitle,
style: const TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: Math.tex(
titles.eq,
mathStyle: MathStyle.display,
textStyle: const TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.bold,
),
),
),
],
);
},
),
),
// Add this
SmoothPageIndicator(
controller: _pageController, // PageController
count: eqs.length,
effect: WormEffect(), // your preferred effect
onDotClicked: (index) {})
],
),
),
),
);
But if you want to have your custom widget for the indicator, instead of updating the active page, update your current index.
Hope you find this helpful!
[AMIR SMILEY]
I am using a textfield in my modal bottom sheet. When I open the keyboard to type, it shows me error for renderflex overflowed. I used singlechildscrollview and isScrollControlled true, still error comes up. Any solutions?
return showModalBottomSheet(
context: context,
builder: (context) => Builder(
builder: (context) => SingleChildScrollView(
child: Container(
height: 350,
width: MediaQuery.of(context).size.width*0.9,
color: cardColor2,
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0, horizontal: 10),
child: Column(
children: [
ValueListenableBuilder(
valueListenable: _image,
builder: (BuildContext context, File f, Widget? child) {
return SizedBox(
height: f.path!='' ? 180 : 280,
width: MediaQuery.of(context).size.width*0.9,
child: TextField(
decoration: InputDecoration(
hintText: 'Type your question here',
border: InputBorder.none,
),
),
);
},
),
ValueListenableBuilder(
valueListenable: _image,
builder: (BuildContext context, File f, Widget? child) {
return f.path!='' ? SizedBox(
width: 150.0,
height: 100.0,
child: Image.file(
_image.value,
fit: BoxFit.fill,
),
) : Container();
},
),
Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Container(
height: 1,
color: tertiaryTextColor2,
width: double.infinity,
),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(top: 13.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
InkWell(
onTap: () {
_onAlertPress(context);
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
child: Text(
'Add an image',
style: TextStyle(
color: backgroundColor2,
fontSize: 14,
),
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
),
SizedBox(
width: 10,
),
InkWell(
onTap: () {
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
child: Text(
'Post',
style: TextStyle(
color: backgroundColor2,
fontSize: 14,
),
),
decoration: BoxDecoration(
color: brandYellow,
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
),
],
),
),
),
],
),
),
],
),
),
),
),
isScrollControlled: true,
);
try to remove height of Container because the height is not enough for other child container or sizedbox
return showModalBottomSheet(
context: context,
builder: (context) => Builder(
builder: (context) => SingleChildScrollView(
child: Container(
height: 350, ---------------> remove this
width: MediaQuery.of(context).size.width*0.9,
I leave the entire code fragment, the main idea is to have a textfield that, by using the keyboard, shows me a series of elements, in the description variable, I have that element to select, this works well, the only issue is, how to keep my alertdialog with all the correct notes.
return await Get.generalDialog(
barrierLabel: "Barrier",
barrierDismissible: false,
transitionBuilder: (context, a1, a2, widget) {
return StatefulBuilder(builder: (context, setState) {
return Transform.scale(
scale: a1.value,
child: Opacity(
opacity: a1.value,
child: Dialog(
insetAnimationCurve: Curves.bounceOut,
insetPadding: EdgeInsets.only(right: 20, left: 20),
//backgroundColor: colorFour(),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
child: SingleChildScrollView(
child: Container(
height: 340,
child: Column(
children: <Widget>[
Container(
alignment: Alignment.topCenter,
height: 50,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
),
),
padding: EdgeInsets.all(5),
child: Center(
child: Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600),
maxLines: 2,
textAlign: TextAlign.center,
),
),
),
SingleChildScrollView(
padding: EdgeInsets.only(left: 10, right: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Container(
margin: EdgeInsets.only(top: 10),
child: TextFormField(
controller: controller,
decoration: InputDecoration(
border: OutlineInputBorder(
gapPadding: 5.0)),
keyboardType: TextInputType.text,
maxLines: 1,
onChanged: (String cadena) async {
listado = pivote
.where((x) => x.descripcion
.split("/")[value]
.toLowerCase()
.contains(
cadena.toLowerCase()))
.toList();
setState(() {});
},
),
),
Container(
height: 200,
margin: EdgeInsets.only(
top: 10, bottom: 10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(5)),
border: Border.all(
color: Colors.grey, width: 1)),
child: ListView.builder(
padding: const EdgeInsets.all(0.0),
physics: BouncingScrollPhysics(),
itemCount: listado.length,
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Container(
height: 34,
child: InkWell(
child: SizedBox.expand(
child: Align(
alignment:
Alignment.centerLeft,
child: Padding(
padding:
EdgeInsets.only(
right: 5,
left: 5),
child: Text(
listado[index]
.descripcion
.split(
"/")[value],
textAlign:
TextAlign.left),
),
),
),
onTap: () {
Get.back(result: {
"item": listado[index],
});
}),
);
}),
),
],
)),
],
),
),
),
),
));
});
},
pageBuilder: (context, animation1, animation2) {
return Container();
});
I need to overlay my alertdialog, that is to say that the size does not break my design, this happens after focusing on the textfield
Show us some code to help you out.
In any case, it might make sense to wrap the layout in a SingleChildScrollView.
Here is a very good explanation.
https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html
yourAlertDialog(
context: context,
builder: (BuildContext context) {
return SingleChildScrollView(child: yourchild);
},
);
Your layout should be wrapped in Scrollview , I didn't replicate or run this code but it should be like this:
AlertDialog(
title: Text("title", style: TextStyle(color: ThemeColors.colorPrimary),),
content: Container(
width: double.maxFinite,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: StatefulBuilder(builder: (BuildContext context1, StateSetter setState) {
this.setState = setState;
return Container(
height: 340,
child: Column(
children: <Widget>[
//your container
],
),
),
}),
)),
);
Flutter & AlertDialog : How do I align it to bottom? How I make 2 Alert Dialogs like this pictures?Please have a lot at this picture.
showDialog(
context: context,
builder: (BuildContext context) {
double width =
MediaQuery.of(context).size.width;
double height =
MediaQuery.of(context).size.height;
return AlertDialog(
backgroundColor: Colors.transparent,
contentPadding: EdgeInsets.zero,
title: Center(
child: Text("Evaluation our APP")),
content: Container(
// What Should I write here?
)
},
);
Here is one of the solutions:
showDialog(
context: context,
builder: (BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return AlertDialog(
backgroundColor: Colors.transparent,
contentPadding: EdgeInsets.zero,
elevation: 0.0,
// title: Center(child: Text("Evaluation our APP")),
content: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
const BorderRadius.all(Radius.circular(10.0))),
child: Column(
children: [
Text("a"),
Divider(),
Text("b"),
Divider(),
Text("c"),
],
),
),
SizedBox(
height: 10,
),
Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
const BorderRadius.all(Radius.circular(10.0))),
child: Center(child: Text("d")),
)
],
));
},
);
here is my answer, pure widget without create AlertDialog:
final content = Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(10.0)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextButton(onPressed: () {}, child: Text("a"),),
Divider(height: 1,),
TextButton(onPressed: () {}, child: Text("b"),),
Divider(height: 1,),
TextButton(onPressed: () {}, child: Text("c"),),
],
),
),
SizedBox(
height: 10,
),
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
const BorderRadius.all(Radius.circular(10.0)),
),
child: TextButton(onPressed: () {}, child: Text("d"),),
),
SizedBox(
height: 40,
),
],
);
showDialog(
context: context,
builder: (ctx) {
return FractionallySizedBox(
widthFactor: 0.9,
child: Material(
type: MaterialType.transparency,
child: content,
),
);
}
);
have to add Material because of text drawing error.
I am designed very heavy nested design like below, the issue when my list expands the listview doesn't seems to be scrolling what is the reason for this, the bottomsheet gets expanded but there is no focus on listview inside it, if i scrolls by touching the 'Operational Hours' text it starts scrolling but when it goes upwards i can't slide it down.
_showDialog(BuildContext context) {
print("_showDialog");
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (BuildContext context) {
return DraggableScrollableSheet(
expand: false,
builder: (context, scrollController) {
return Container(
child: Stack(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Container(
margin: EdgeInsets.symmetric(vertical: 8),
height: 8.0,
width: 70.0,
decoration: BoxDecoration(
color: Colors.grey[400],
borderRadius: BorderRadius.circular(10.0)))),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Text('Operational Hours',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: widget.isTab(context)
? TabTextStyles.mediumText
.copyWith()
.fontSize
: PhoneTextStyles.mediumText
.copyWith()
.fontSize)),
),
],
),
ListView(
controller: scrollController,
children: <Widget>[
SizedBox(height: 54.0),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 20.0),
Text('Select days to add hours',
style: widget.isTab(context)
? TabTextStyles.mediumText.copyWith()
: PhoneTextStyles.mediumText.copyWith()),
]),
),
DaysList()
],
),
],
),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Theme.of(context).backgroundColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24.0),
topRight: Radius.circular(24.0),
),
),
);
},
);
},
);
}
There are couple of mistakes you're making. First, put widgets in Column that are always going to be visible at top, second wrap your DaysList in Expanded and pass ScrollController to it.
This is your method:
void _showDialog(BuildContext context) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (BuildContext context) {
return DraggableScrollableSheet(
expand: false,
builder: (context, scrollController) {
return Column(
children: <Widget>[
// Put all heading in column.
column,
// Wrap your DaysList in Expanded and provide scrollController to it
Expanded(child: DaysList(controller: scrollController)),
],
);
},
);
},
);
}
This is your Column:
Widget get column {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Container(
margin: EdgeInsets.symmetric(vertical: 8),
height: 8.0,
width: 70.0,
decoration: BoxDecoration(color: Colors.grey[400], borderRadius: BorderRadius.circular(10.0)),
),
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Text('Operational Hours', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 20.0),
Text('Select days to add hours'),
],
),
),
SizedBox(height: 16),
],
);
}
And this is how your DaysList should look like:
class DaysList extends StatelessWidget {
final ScrollController controller;
const DaysList({Key key, this.controller}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
controller: controller, // assign controller here
itemCount: 20,
itemBuilder: (_, index) => ListTile(title: Text("Item $index")),
);
}
}
Output:
Screenshot:
Call this method:
void showMyBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (_) {
return DraggableScrollableSheet(
maxChildSize: 0.8,
expand: false,
builder: (_, controller) {
return Column(
children: [
Container(
width: 100,
height: 8,
margin: EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.grey,
),
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: 100,
itemBuilder: (_, i) => ListTile(title: Text('Item $i')),
),
),
],
);
},
);
},
);
}