My code:
```flutter
Widget _buildActionForTask(TaskInfo task) {
if (task.status == DownloadTaskStatus.undefined) {
return new RawMaterialButton(
onPressed: () {
_requestDownload(task); /*download button*/
},
child: new Icon(
Icons.file_download,
size: 30,
),
shape: new CircleBorder(),
constraints: new BoxConstraints(minHeight: 32.0, minWidth: 32.0),
);
} else if (task.status == DownloadTaskStatus.running) {
/*there is my stuck*/
return new RawMaterialButton(
onPressed: () {
_pauseDownload(task); /*pause button*/
},
child: new Icon(
Icons.pause,
size: 30,
color: Colors.white,
),
shape: new CircleBorder(),
constraints: new BoxConstraints(minHeight: 32.0, minWidth: 32.0),
);
} else if (task.status == DownloadTaskStatus.paused) {
return new RawMaterialButton(
onPressed: () {
_resumeDownload(task); /*resume button*/
},
child: new Icon(
Icons.play_arrow,
size: 30,
color: Colors.green,
),
shape: new CircleBorder(),
constraints: new BoxConstraints(minHeight: 32.0, minWidth: 32.0),
);
}
Here is my appbar:
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Image ${this.widget.index}"),
Builder(
builder: (context) => _isLoading
? Center(
child: CircularProgressIndicator(),
)
: _permissionReady
? _buildActionForTask(taskInfo)
: FlatButton(
onPressed: () {
_checkPermission().then((hasGranted) {
setState(() {
_permissionReady = hasGranted;
});
});
},
child: Text(
"Thử lại",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20.0),
)),
)
],
),
flexibleSpace: GradientBar(),
),
I am creating a function to download. After I hit the download button, it encountered this error. Download and delete buttons are displayed normally.
I tried many ways but still got that error. I still don't know how it can overflow 99788px?
Don't use a Row inside title, try using just the text widget and move the other widgets (, the one inside builder) to the action parameter, it accepts a list of widgets to the right of the appbar
Try wrapping your button with a Container and giving it fixed width.
You can also try to give fixed width to your constraints
Related
My application does not get the alignment problem in the examples I will show below while running on android devices. When I want to run it on my iOS device, I have the following alignment problem.
Problematic alignment starts here. My app experiences a completely symmetrical change when I choose the Persian or Arabic language and some emojis are aligned properly while others appear distorted.
My Code :
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: ortaMavi,
leading: IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: Icon(
Icons.arrow_back_ios,
size: 20,
color: Colors.white,
)),
title: Center(child: Text(titleHolder)),
actions: <Widget>[
Center(
child: Container(
margin: EdgeInsets.all(15),
child: Text(
flagHolder,
style: TextStyle(fontSize: 25),
)),
)
],
),
body: SafeArea(
child: ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 5),
itemCount: countries.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
EasyLocalizationProvider.of(context)
.data
.changeLocale(langs[index]);
setState(() {
titleHolder = countries[index];
flagHolder = flags[index];
selectedLangIndex = index;
});
},
child: Container(
decoration: BoxDecoration(
color:
selectedLangIndex != null && selectedLangIndex == index
? ortaMavi.withOpacity(0.2)
: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.lightBlueAccent.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 3,
offset: Offset(0, 3), // changes position of shadow
),
],
),
height: 50,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'${countries[index]}',
style: TextStyle(
fontSize: 20,
color: selectedLangIndex != null &&
selectedLangIndex == index
? Colors.white
: Colors.black),
),
Text(
flags[index],
style: TextStyle(fontSize: 25),
)
],
),
),
),
);
}),
),
);
}
You can put the flags String inside a SizedBox
SizedBox(
width: 200.0,
height: 200.0,
child:Text(
flags[index],
),
)
says Undefined name 'context' in Navigator.push.
If i put context in Navigator.push it says that context is undefined name.
Even after importing the required file it does not seem to work the way i it should.
Widget btn() {
if (index == 0) {
return Container(
padding: EdgeInsets.all(30.0),
child: FloatingActionButton.extended(
onPressed: () {
Route route = MaterialPageRoute(builder: (context) => Exp());
Navigator.push(context,route);
},
backgroundColor: Colors.grey[100],
elevation: 4.0,
label: Text(
'Skip',
style: TextStyle(fontSize: 20.0, color: Colors.pink),
),
icon: Icon(
Icons.keyboard_arrow_right,
color: Colors.pink,
size: 30.0,
),
),
);
} else if (index == 2) {
return Container(
padding: EdgeInsets.all(20.0),
child: FloatingActionButton.extended(
onPressed: ()=>null,
backgroundColor: Colors.grey[100],
elevation: 4.0,
label: Text(
'Explore',
style: TextStyle(fontSize: 20.0, color: Colors.pink),
),
icon: Icon(
Icons.keyboard_arrow_right,
color: Colors.pink,
size: 30.0,
),
),
);
} else {
return Text('');
}
}
I have a ListTile of cards going down my page but I don't have an AppBar in my app, so the ListTile starts at the top of the page. If I add padding, it adds it to each card in the ListView and then whilst I can position the cards lower in the page, I get huge gaps between them. Is there any way in which I can maintain the small gap that I would like in between the cards but simply have a larger gap at the top before the ListView begins? For reference, I pasted the code below. (Essentially it is a Todo list type app, so there is a FormField that pops ups from the bottom and you enter a task it appears on the card in the ListView.)
Widget _buildTodoList() {
DateTime now = DateTime.now();
String formattedDate = DateFormat('EEE d MMM').format(now);
return ListView.builder(
itemBuilder: (context, index) {
if(index < _todoItems.length) {
return ListTile(
onLongPress: () => _promptRemoveTodoItem(index),
title: Card(
elevation: 1.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(23.0),
),
semanticContainer: true,
clipBehavior: Clip.antiAlias,
child: Column(
children: <Widget>[
Container(
child: Stack(
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(23.5, 27.5, 0.0, 0.0),
child: Text("?",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: Colors.black54,
),
),
),
Container(
margin: EdgeInsets.fromLTRB(23.5, 58.0, 0.0, 0.0),
child: Text("${_todoItems[index]}",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12,
color: Colors.black38,
),
),
),
Align(
alignment: Alignment.centerRight,
child: Container(
margin: EdgeInsets.fromLTRB(0.0, 6.5, 20.0, 0.0),
child: Text(formattedDate,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 11,
color: Colors.deepOrange[700],
),
),
),
),
],
),
height: 100,
width: 380,
),
],
),
),
);
}
},
);
}
I'm not sure if I understand your problem correct, but if it's - I see a couple of solutions:
You can add padding to whole ListView
Padding(padding: EdgeInsets.only(top: 200.0), child: ListView.builder(...),)
You can add empty item on first place in list:
ListView.builder(itemBuilder: (context, index) {
if (index == 0) {
return SizedBox(height: 200.0,);
} else {
// todo return your ListTile
}
},
itemCount: _todoItems.length + 1,)
Im fairly new to flutter,
I have created a nice BottomAppBar with a docked FAB however i also want to use this AppBar for page navigation. I've tried it with a BottomNavigationBar but then i lose the docked floating action button. How can i implement navigation into the bottom app bar??
floatingActionButton: Container(
height: 65.0,
width: 65.0,
child: FittedBox(
child: FloatingActionButton(
onPressed: (){},
child: Icon(Icons.add, color: Colors.white,),
// elevation: 5.0,
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
// elevation: 20.0,
shape: CircularNotchedRectangle(),
child: Container(
height: 75,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
iconSize: 30.0,
padding: EdgeInsets.only(left: 28.0),
icon: Icon(Icons.home),
onPressed: () {
setState(() {
currentIndex = 0;
});
},
),
IconButton(
iconSize: 30.0,
padding: EdgeInsets.only(right: 28.0),
icon: Icon(Icons.search),
onPressed: () {
setState(() {
currentIndex = 1;
print("${currentIndex}");
});
},
),
IconButton(
iconSize: 30.0,
padding: EdgeInsets.only(left: 28.0),
icon: Icon(Icons.notifications),
onPressed: () {
setState(() {
currentIndex = 2;
print("${currentIndex}");
});
},
),
IconButton(
iconSize: 30.0,
padding: EdgeInsets.only(right: 28.0),
icon: Icon(Icons.list),
onPressed: () {
setState(() {
currentIndex = 3;
print("${currentIndex}");
});
},
)
],
),
)
)
One Way of Doing it is with - PageView widget.
Example Code with your Coded BottomAppBar.
class _DemoPageState extends State<FormPage> {
PageController _myPage = PageController(initialPage: 0);
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
child: Container(
height: 75,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
iconSize: 30.0,
padding: EdgeInsets.only(left: 28.0),
icon: Icon(Icons.home),
onPressed: () {
setState(() {
_myPage.jumpToPage(0);
});
},
),
IconButton(
iconSize: 30.0,
padding: EdgeInsets.only(right: 28.0),
icon: Icon(Icons.search),
onPressed: () {
setState(() {
_myPage.jumpToPage(1);
});
},
),
IconButton(
iconSize: 30.0,
padding: EdgeInsets.only(left: 28.0),
icon: Icon(Icons.notifications),
onPressed: () {
setState(() {
_myPage.jumpToPage(2);
});
},
),
IconButton(
iconSize: 30.0,
padding: EdgeInsets.only(right: 28.0),
icon: Icon(Icons.list),
onPressed: () {
setState(() {
_myPage.jumpToPage(3);
});
},
)
],
),
),
),
body: PageView(
controller: _myPage,
onPageChanged: (int) {
print('Page Changes to index $int');
},
children: <Widget>[
Center(
child: Container(
child: Text('Empty Body 0'),
),
),
Center(
child: Container(
child: Text('Empty Body 1'),
),
),
Center(
child: Container(
child: Text('Empty Body 2'),
),
),
Center(
child: Container(
child: Text('Empty Body 3'),
),
)
],
physics: NeverScrollableScrollPhysics(), // Comment this if you need to use Swipe.
),
floatingActionButton: Container(
height: 65.0,
width: 65.0,
child: FittedBox(
child: FloatingActionButton(
onPressed: () {},
child: Icon(
Icons.add,
color: Colors.white,
),
// elevation: 5.0,
),
),
),
);
}
}
The difference between the BottomAppBar and the BottomNavigationBar, is that with the last one, you can set a list of children (pages) to be rendered as you click on the icons below (onTap method). With the BottomAppBar, you have to set a Navigator method, speaking in UI/UX terms, I don't think it's very beauty to see.
Create an auxiliar component, which will have the BottomAppBar.
Then, pass a Row as the child method of it
Fill with your IconButtons
Set the onPressed methods to call the pages (Navigator.of(context).pushName('/yourScreenHere')
Then, for every screen you make you can add an AppBar on them.
You can use a switch case for your body using the same scaffold - Like in tabcontroller or radiobutton.
Just update the body when bottomAppBar icon is pressed.
Check out this link for better understanding. :)
I use this method to show a AlertDialog:
_onSubmit(message) {
if (message.isNotEmpty) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Center(child: Text('Alert')),
content: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children : <Widget>[
Expanded(
child: Text(
message,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.red,
),
),
)
],
),
actions: <Widget>[
FlatButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
}),
FlatButton(
child: Text('Ok'),
onPressed: () {
_inputTextController.clear();
Navigator.of(context).pop();
})
],
);
},
);
}
}
Everything is working but the buttons are aligned in right as shown on picture below:
I want to style some how the buttons, for example one on start other on end.
I searched in docs but only found how to make them "Stacked full-width buttons".
Any ideas how to style the buttons?
Update 2022/10/22
Flutter 2.5 introduced the actionsAlignment property:
AlertDialog(
title: ..
actions: ..
actionsAlignment: MainAxisAlignment.end
),
Customize widget
Edit the the widget itself: Under the AlertDialog there is a ButtonBar widget where you can use alignment: MainAxisAlignment.spaceBetween to align the buttons correctly. See this answer for an example of a custom AlertDialog widget.
Own button row
You could also remove the buttons under actions and add an own custom Row with RaisedButtons in it, somehow like this:
Row (
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RaisedButton(), // button 1
RaisedButton(), // button 2
]
)
In your case you could add a Column around the Row in content and in there add your existing Row and the modified one you created from the above example.
Move buttons to content is a good solution.
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Center(child: Text('Alert')),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: Text(
"message",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.red,
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
child: Text('Yes'),
onPressed: () {
Navigator.of(context).pop();
}),
FlatButton(
child: Text('No'),
onPressed: () {
Navigator.of(context).pop();
})
])
],
),
);
});
Changing the theme is a good option.
MaterialApp(
theme: ThemeData(
buttonBarTheme: ButtonBarThemeData(
alignment: MainAxisAlignment.center,
)),
...
Don't add button in actions of AlertDialog. As you can see.
_onSubmit(message) {
if (message.isNotEmpty) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Center(child: Text('Alert')),
content: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children : <Widget>[
Expanded(
child: Text(
message,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.red,
),
),
),
FlatButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
}),
FlatButton(
child: Text('Ok'),
onPressed: () {
_inputTextController.clear();
Navigator.of(context).pop();
})
],
),
);
},
);
}
}
I use this method to align buttons in actions of AlertDialog.
How this works::
The SizedBox takes the full width of the alertdialog using its context(In the statement MediaQuery.of(context).size.width. After that, a row is used which places space between its children in the main axis(mainAxisAlignment => the x-axis for a row).
AlertDialog style:
AlertDialog(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Title'),
CloseButton(
color: Color(0xFFD5D3D3),
onPressed: () {
Navigator.of(context).pop();
})
]),
content: SingleChildScrollView(child: Text("Boby")),
actions: [
SizedBox(
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ButtonTheme(
minWidth: 25.0,
height: 25.0,
child: OutlineButton(
borderSide: BorderSide(color: Colors.blueAccent),
child: new Text("Save"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
onPressed: () {})),
SizedBox(width: 8.0),
ButtonTheme(
minWidth: 25.0,
height: 25.0,
child: OutlineButton(
borderSide: BorderSide(color: Colors.black26),
textColor: Colors.blue,
child: new Text("Close"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
onPressed: () {}))
]))
]);
Here is the straightforward answer for your problem:
Just use actionsAlignment property of AlertDialog class in flutter. Like so
AlertDialog(
actions: ...,
actionsAlignment: MainAxisAlignment.spaceBetween
)
Or you can use RFlutter Alert library for that. It is easily customizable and easy-to-use. Its default style includes rounded corners and you can add buttons as much as you want.
Alert Style:
var alertStyle = AlertStyle(
animationType: AnimationType.fromTop,
isCloseButton: false,
isOverlayTapDismiss: false,
descStyle: TextStyle(fontWeight: FontWeight.bold),
animationDuration: Duration(milliseconds: 400),
alertBorder: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0),
side: BorderSide(
color: Colors.grey,
),
),
titleStyle: TextStyle(
color: Colors.red,
),
);
And assing your AlertStyle object to Alert's style field.
Alert(
context: context,
style: alertStyle,
type: AlertType.info,
title: "RFLUTTER ALERT",
desc: "Flutter is more awesome with RFlutter Alert.",
buttons: [
DialogButton(
child: Text(
"COOL",
style: TextStyle(color: Colors.white, fontSize: 20),
),
onPressed: () => Navigator.pop(context),
color: Color.fromRGBO(0, 179, 134, 1.0),
radius: BorderRadius.circular(0.0),
),
],
).show();
*I'm one of developer of RFlutter Alert.