I have a working Alertdialog but I get an overflow error and I can't get rid of it. I have tried flexible and expanded but maybe on the wrong levels.
builder: (BuildContext context) => AlertDialog(
title: const Center(child: Text('Completing task')),
content: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
UnconstrainedBox(
child: Flexible(
child: Column(
children: [
Text('Tag: ' + task.tag),
Text("rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr"),
const SizedBox(height: 10),
const Text('Waiting for NFC'),
const SizedBox(height: 20),
const Center(
child: CircularProgressIndicator(
color: Colors.grey,
),
),
],
),),
),
],
),
The issue here is the long text. If you would like all of the text to display without overflowing the layout, then Flexible is an option. Wrap the Text element with a Flexible when the displayed text could potentially be longer than the width of the view.
Notice that I had to remove some unnecessary elements from the view. Those elements were misplaced/misused for this scenario and were adding to the problem.
There are other ways to handle this, but I like how flexible (pun intended) this option is without having to calculate or guess width/height.
Here is a solution with the code cleaned up a little and using the Flexible on the long text element.
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Center(child: Text('Completing task')),
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Tag: P1348'),
Flexible(child: Text("rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr"),),
const SizedBox(height: 10),
const Text('Waiting for NFC'),
const SizedBox(height: 20),
const Center(
child: CircularProgressIndicator(
color: Colors.grey,
),
),
],
)
);
}
);
Container(
child: Text('text',
overflow: TextOverflow.fade,
maxLines: 1,
softWrap: false,
),
width: 50,
),
SizedBox(
width: YourOwnWidth,
child: Text("rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr",style: TextStyle(
overflow: TextOverflow.clip
),),
);
an Easy solution that you can use
Related
Need help. I have created a column on the page inside which there are 2 more columns, so I moved the buttons that are at the bottom to the very bottom so that they are always at the bottom of the screen. But when I add a SingleChildScrollView to make the page scroll, the space between the columns disappears and the bottom buttons move under other widgets. How can I solve the problem so that when adding a SingleChildScrollView, there is an empty space and the buttons remain at the very bottom of the screen?
body
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
const SizedBox(height: 121.0),
BackStepWidget(
text: 'Balance: $coins',
textStyle: constants.Styles.largeHeavyTextStyleWhite,
),
const Text(
'Buy JoinCoins',
style: constants.Styles.bigHeavyTextStyleWhite,
),
const Image(
image: AssetImage('assets/images/image.png'),
),
const Text('I Want To Buy',
style: constants.Styles.smallBoldTextStyleWhite),
const SizedBox(height: 10),
const CoinsCounterWidget(),
const SizedBox(height: 10),
const Text('JoynCoins',
style: constants.Styles.smallBoldTextStyleWhite),
],
),
Column(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 24),
child: DefaultButtonGlow(
text: 'Buy me JoynCoins for 100% battery.',
color: constants.Colors.greyLight.withOpacity(0.4),
textStyle: constants.Styles.buttonTextStyle,
shadowColor: Colors.transparent,
borderColor: constants.Colors.purpleMain,
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return const DefaultAlertDialog(
text:
'Please set a payment method for buying JoynCoins.',
);
},
);
},
),
),
Padding(
padding: const EdgeInsets.only(bottom: 47),
child: DefaultButtonGlow(
text: 'Buy Now ',
color: constants.Colors.purpleMain,
textStyle: constants.Styles.buttonTextStyle,
shadowColor: constants.Colors.purpleMain,
borderColor: constants.Colors.purpleMain,
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return const DefaultAlertDialog(
text: "You'r about to buy",
isText2: true,
text2: '2500 JoynCoins',
);
});
},
),
)
],
)
],
),
));
Added SingleChildScrollView
Without SingleChildScrollView
You can simplify this code to understand the issue. MainAxisAlignment.spaceBetween will provide maximum spaces between widgets.
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("top"),
Text("bottom"),
],
),
Once you wrapped with SingleChildScrollView, Column takes minimum height for its children and become,
You can use SizedBox to provide space between items. You can use LayoutBuidler that I've posted on your previous question. For this I am using MediaQuery
body: SingleChildScrollView(
child: Column(
children: [
Text("top"),
SizedBox(
height: MediaQuery.of(context).size.height * .4,
), // you custom height
Text("bottom"),
],
),
),
Use SizedBox in between Columns or use the following inside Singlechildscrollview
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
here is the UI that I'm trying to build
but this is the output
I tried alignment also , but that also didn't working
but when setting a fixed height this is working fine
but I can't fill this using the fit parameter,
here is the code
Scaffold(
backgroundColor: kDarkTheme,
body: SafeArea(
child: Column(
children: [
const SizedBox(height: 10),
Row(
//code for top button
),
const SizedBox(height: 150),
Stack(
children: [
Center(
child: CircleAvatar(
radius: radiusSize + 5,
backgroundColor: kDarkCounterColor,
child: CircleAvatar(
backgroundColor: kDarkTheme,
radius: radiusSize,
),
),
),
Center(
child: Padding(
padding: const EdgeInsets.only(top: 35),
child: Text(
'39',
style: GoogleFonts.italiana(
fontSize: 120, color: kDarkCounterColor),
),
),
),
],
),
const SizedBox(height: 15),
const Text(
'Tap To Count',
style: TextStyle(
fontFamily: 'Helvatica',
color: Color(0xff656158),
),
),
Expanded(
child: Align(
alignment: Alignment.bottomRight,
child: SvgPicture.asset(
kDarkThemeImage,
)),
)
],
),
))
this is the code
then the first error appears again. how could I fix this?
You are using the Expanded widget on a column that doesn't have a set size. Try adding MainAxisSize attribute to your column, like this:
Column(
mainAxisSize: MainAxisSize.max, // Add this like
children: [
...
This will make your column fit the whole available size on the previous widget (a scaffold for the whole screen). Then the expanded widget will fill the remaining space not used by the other widgets inside the column.
In the project I'm currently working on, I have a Scaffold that contains a SinlgeChildScrollView. Within this SingleChildScrollView the actual content is being displayed, allowing for the possibility of scrolling if the content leaves the screen.
While this makes sense for ~90% of my screens, however I have one screen in which I display 2 ExpansionTiles. Both of these could possibly contain many entries, making them very big when expanded.
The problem right now is, that I'd like the ExpansionTile to stop expanding at latest when it reaches the bottom of the screen and make the content within the ExpansionTile (i.e. the ListTiles) scrollable.
Currently the screen looks like this when there are too many entries:
As you can clearly see, the ExpansionTile leaves the screen, forcing the user to scroll the actual screen, which would lead to the headers of both ExpansionTiles disappearing out of the screen given there are enought entries in the list. Even removing the SingleChildScrollView from the Scaffold doesn't solve the problem but just leads to a RenderOverflow.
The code used for generating the Scaffold and its contents is the following:
class MembershipScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MembershipScreenState();
}
class _MembershipScreenState extends State<MembershipScreen> {
String _fontFamily = 'OpenSans';
Widget _buildMyClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
title: Text("My Clubs"),
trailing: Icon(Icons.add),
children: getSearchResults(),
),
)
);
}
Widget _buildAllClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: SingleChildScrollView(
child: ExpansionTile(
title: Text("All Clubs"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add)
],
),
children: getSearchResults(),
),
)
)
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: kGradient //just some gradient
),
),
Center(
child: Container(
height: double.infinity,
constraints: BoxConstraints(maxWidth: 500),
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Clubs',
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
fontFamily: _fontFamily,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 20,
),
_buildMyClubs(),
SizedBox(height: 20,),
_buildAllClubs()
],
),
),
),
),
],
),
)
),
);
}
List<Widget> getSearchResults() {
return [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
}
}
I hope I didn't break the code by removing irrelevant parts of it in order to reduce size before posting it here. Hopefully, there is someone who knows how to achieve what I intend to do here and who can help me with the solution for this.
EDIT
As it might not be easy to understand what I try to achieve, I tried to come up with a visualization for the desired behaviour:
Thereby, the items that are surrounded with dashed lines are contained with the list, however cannot be displayed because they would exceed the viewport's boundaries. Hence the ExpansionTile that is containing the item needs to provide a scroll bar for the user to scroll down WITHIN the list. Thereby, both ExpansionTiles are visible at all times.
Try below code hope its help to you. Add your ExpansionTile() Widget inside Column() and Column() wrap in SingleChildScrollView()
Refer SingleChildScrollView here
Refer Column here
You can refer my answer here also for ExpansionPanel
Refer Lists here
Refer ListView.builder() here
your List:
List<Widget> getSearchResults = [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
Your Widget using ListView.builder():
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children: [
ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Column(
children: getSearchResults,
);
},
itemCount: getSearchResults.length, // try 50 length just testing
),
],
),
),
],
),
),
Your Simple Widget :
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children:getSearchResults
),
),
],
),
),
Your result screen ->
I've been toying with lists in flutter, and everything is fine. I'm starting to understand the logic of the whole thing.
Now I wanted to do a simple layout like that :
My problem is that I can't find a way to make the first row. I tried to tell Row to let its two children take half and no less no more, but I didn't really find a way. (The inside thing will eventually be buttons.)I tried several things to no avail. Here is the layout I started from :
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 50.0),
),
Row(
children: <Widget>[
Padding(
padding: EdgeInsets.only(
top: buttonPaddingTop,
left: buttonPaddingSide,
right: buttonPaddingSide),
child: ButtonTheme(
child: FlatButton(
onPressed: () {},
color: Colors.grey,
child: const Text('LARGE TEXT',
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: buttonFontSize)),
),
),
),
Padding(
padding: EdgeInsets.only(
top: buttonPaddingTop,
left: buttonPaddingSide,
right: buttonPaddingSide),
child: ButtonTheme(
child: FlatButton(
onPressed: () {},
color: Colors.grey,
child: const Text('LARGE TEXT',
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: buttonFontSize)),
),
),
),
],
),
]),
),
);
}
Should I continue trying like this, or should I try another object than Row to arrange the layout ?
Expanded takes as much space as available in this case horizontally. That means if you would use 2 Expanded widgets inside your Row, the space will be divided by half.
Try this:
Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Text('first half'),
),
Expanded(
child: Text('second half'),
),
],
),
Row(
children: <Widget>[
Expanded(
child: Text('first half'),
),
Expanded(
child: Text('second half'),
),
],
),
Row(
children: <Widget>[
Expanded(
child: Text('full width'),
)
],
),
],
)
Make sure you read more about Flutter widgets, for example watch this video (and other ones in this series):
https://www.youtube.com/watch?v=_rnZaagadyo
I am making a flutter application in which i uses body as a stack and in this stack i have two child.One is main body and other is back button which is at top of screen.The first child of stack is scrollview.Here is my build method.
Widget build(BuildContext context) {
return Scaffold(
//debugShowCheckedModeBanner: false,
key: scaffoldKey,
backgroundColor: Color(0xFF5E68A6),
body: Stack(
children: <Widget>[
Container(
margin: const EdgeInsets.fromLTRB(0.0, 10.0 , 0.0 , 0.0 ),
height: double.infinity,
child:CustomScrollView(
slivers: <Widget>[
new Container(
margin: EdgeInsets.all(15.0),
child:Text(getTitle(),
style: TextStyle(fontSize: 20.0,fontWeight: FontWeight.bold,color: Colors.white),
),
),
//middle section
_isLoading == false ?
new Expanded(child: GridView.builder(
itemCount: sub_categories_list.length,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (context, position){
return InkWell(
child: new Container(
//color: Colors.white,
padding: EdgeInsets.all(20),
margin: EdgeInsets.all(10),
height: 130,
width: 130,
child: new Center(
child :
Text(sub_categories_list[position].name,
style: TextStyle(fontSize: 18.0,fontWeight: FontWeight.bold),
)
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(16)),
// border: Border.all(color: Colors.black, width: 3),
),
),
onTap: () {
//write here
// Fluttertoast.showToast(msg: "You clicked id :"+sub_categories_list[position].cat_id.toString());
Navigator.pushNamed(context, '/advicemyself');
},
);
}
))
:
CircularProgressIndicator(),
Container(
margin: EdgeInsets.all(18.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Column(
children: <Widget>[
Image.asset('assets/bt1.png'),
Container(
margin: EdgeInsets.all(10.0),
child: Text("FIND HELP",
style: TextStyle(fontSize: 18.0,color: Colors.white),
),
)
],
),
new Column(
children: <Widget>[
Image.asset('assets/bt2.png'),
Container(
margin: EdgeInsets.all(10.0),
child: Text("HOME",
style: TextStyle(fontSize: 18.0,color: Colors.white),
),
)
],
),
new Column(
mainAxisAlignment:MainAxisAlignment.spaceEvenly,
children: <Widget>[
Image.asset('assets/bt3.png'),
Container(
margin: EdgeInsets.all(10.0),
child: Text("CALL 999",
style: TextStyle(fontSize: 18.0,color: Colors.white),
),
)
],
),
],
),
),
],
),
),
Positioned(
left: 10,
top: 30,
child: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => {
//go back
},
color: Colors.white,
iconSize: 30,
),
),
// makeview()
],
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
I have also tried using SingleChildScrollView but that also does not works.What i am doing wrong here ?
Here is link to the design which i want to make.
https://imgur.com/a/w7nLmKC
The back should be above scroll view so i used stack widget.
Running your sample code, there doesn't seem to be a need for overlapping widgets. Using Stack seems to be unnecessary. One way you could do is by using Column widget, and using Expanded as you see fit.
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Widget(), // back button goes here
CustomScrollView(...),
],
),
);
}
Otherwise, if you really need to use Stack, the scroll function should work fine. I've tried this locally and the Stack widget doesn't interfere with scrolling of Slivers, ListView, and GridView.
Stack(
children: [
/// Can be GridView, Slivers
ListView.builder(),
/// Back button
Container(),
],
),