How to position elements inside a ListView? - dart

Good morning. I made this screen and it works like a charm on high resolutions. Problem is, I want to support lower resolutions like Nexus 4 (768x1280).
So when I run this on an emulator (Nexus 4 size) and I touch the input fields, the keyboard either: blocks the inputs, or moves the two buttons at the bottom and overlaps them on something else.
So, to solve it I wrapped the entire layout on a ListView(), but now the bottom buttons, which are wrapped on a Row(), just won't stay at the bottom.
This is my code without the ListView and working on high res, but not on low:
return Form(
Stack(
Center(
Column(
...
),
),
Align(
alignment: Alignment.bottomCenter,
child: Row(
...
),
),
),
);
This is how it looks with resizeToAvoidBottomPadding: false
And this is how it looks with the value set to true
Thanks, everyone.

Did you try to use SingleChildScrollView ?
It is a widget for making the page able to resize the height and as well scrolling , for the listview thats not what is the listview for , you should add listview when you get an unknown amount of data,
We don't normally use it to just adjust the view.
ok so i edited the code as in here and i can scroll normally after the keyboard pop up and the view is good and i can click on the button normally try it.
Widget formWidget(){
return new Scaffold(
// appBar: AppBar(
// // Here we take the value from the MyHomePage object that was created by
// // the App.build method, and use it to set our appbar title.
// title: Text(widget.title),
// ),
body:Column(
children: <Widget> [
Expanded(
child:SingleChildScrollView(
child: Form(
child:
// Stack(
// children: <Widget>[
// Center(
// child: SingleChildScrollView(
// child:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: (MediaQuery.of(context).size.height) > 600
? const EdgeInsets.only(top: 0.0)
: const EdgeInsets.only(top: 30.0),
child: Image(
image: AssetImage('assets/favIcon.png'),
width: 88.0,
height: 88.0,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 28.0, 0, 12.0),
child: Text(
'Delegados',
style: TextStyle(
fontFamily: 'Archia',
fontSize: 32.0,
),
),
),
Text(
'Introduce tus datos de acceso aquí.',
style: TextStyle(
color: Color(0xff83868F),
fontFamily: 'Brutal',
fontSize: 14.0,
),
),
Padding(
padding:
const EdgeInsets.fromLTRB(16.0, 26.0, 16.0, 12.0),
child: TextFormField(
decoration: InputDecoration(
labelText: 'Correo',
filled: true,
fillColor: Color(0xffF0F1F5),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
),
),
style: TextStyle(
fontFamily: 'Brutal',
color: Color(0xff1A1B1F),
),
controller: TextEditingController() ,
textInputAction: TextInputAction.next,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 12.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Contraseña',
filled: true,
fillColor: Color(0xffF0F1F5),
suffixIcon: Icon(Icons.remove_red_eye),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
),
),
style: TextStyle(
fontFamily: 'Brutal',
color: Color(0xff1A1B1F),
),
controller: TextEditingController() ,
//focusNode:FocusNode(),
obscureText: true,
),
),
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 26.0),
child: CupertinoButton(
onPressed: () {},
child: Text(
'Olvidé mi Contraseña',
style: TextStyle(
color: Color(0xff565A66),
fontFamily: 'Brutal',
fontSize: 14.0,
),
),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 0),
child: ButtonTheme(
minWidth: double.infinity,
child: InkWell(
// onTap: state is! LoginLoading
// ? _onLoginButtonPressed
// : null,
child: Container(
height: 48.0,
width: 500.0,
decoration: BoxDecoration(
color: Color(0xff00CC36),
borderRadius: BorderRadius.circular(8.0),
),
child: Align(
alignment: Alignment.center,
child: Container(
child:
// state is LoginLoading
// ? CircularProgressIndicator():
Text(
'INGRESAR AHORA ›',
style: TextStyle(
color: Colors.white,
fontFamily: 'Brutal',
fontSize: 14.0,
),
),
)),
),
),
),
),
],
),
// ),
)
,
// aqui va <<<<<<<<<<<<
// ],
// ),
)
),
Align(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CupertinoButton(
onPressed: () {},
child: Text(
'¿No tienes cuenta?',
style: TextStyle(
color: Color(0xff83868F),
fontFamily: 'Brutal',
fontSize: 14.0,
),
),
),
InkWell(
onTap: null,
child: Container(
height: 32.0,
width: 112.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.0),
border: Border.all(
color: Color(0xffD7D9E0),
width: 1.0,
),
),
child: Align(
alignment: Alignment.center,
child: Text(
'CONTACTANOS',
style: TextStyle(
color: Color(0xff565A66),
fontFamily: 'Brutal',
fontSize: 11.0),
),
),
),
),
],
),
),
]
)
,
// )
);
}

In your Scaffold can you try this.
Scaffold(
resizeToAvoidBottomInset: false,
...
);

I position two elements in the center and bottom of the screen by this code.
body: Column(
children: [
Expanded(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: 80,
width: 80,
child:
Image(image: AssetImage("assets/images/logo.png"))),
SizedBox(height: 10),
Text(
"Tings App",
style: TextStyle(fontSize: 36),
),
SizedBox(height: 10),
TextFormField(
controller: _emailController,
decoration: InputDecoration(
border: OutlineInputBorder(),
isDense: true,
labelText: 'Email/phone'),
validator: (value) {
if (value.isEmpty) {
return 'Please enter a valid email';
}
return null;
},
),
],
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
_isLoading
? CircularProgressIndicator()
: SizedBox(
width: MediaQuery.of(context).size.width * 0.7,
height: 60.0,
child: ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100.0),
),
),
),
child: Text(
"SignIn",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w800,
fontSize: 18),
),
onPressed: () {
_login(context);
},
),
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Don't have account?",
style: TextStyle(fontSize: 16),
),
SizedBox(width: 6),
TextButton(
onPressed: () {
Navigator.push(
context, SlideRightRoute(page: Signup()));
},
child: Text("SignUp"),
),
],
)
],
),
),
)
],
),

Related

RenderCustomMultiChildLayoutBox object was given an infinite size during layout error

I keep getting the error as mentioned when I try to load LessonPage. What is happening is that I have a RootPage which checks if a user is signed in, if he is the RootPage will show the LessonPage but if he is not, it will show the LoginScreen which when the user logs in, will invoke a callback function to RootPage _onLoggedIn()so as to switch pages to the LessonPage.
Update: I found out that the error is also logged when I load the app (i.e. the app opens to a LoginScreen), however I see my login screen instead of a blank screen. I've appended my LoginScreen code below for reference
Root Page:
class RootPage extends StatefulWidget {
RootPage({this.auth});
final BaseAuth auth;
#override
State<StatefulWidget> createState() => new _RootPageState();
}
enum AuthStatus {
NOT_DETERMINED,
NOT_LOGGED_IN,
LOGGED_IN,
}
class _RootPageState extends State<RootPage> {
AuthStatus authStatus = AuthStatus.NOT_DETERMINED;
String _userId = "";
#override
void initState() {
super.initState();
widget.auth.getCurrentUser().then((user) {
setState(() {
if (user != null) {
_userId = user?.uid;
}
authStatus =
user?.uid == null ? AuthStatus.NOT_LOGGED_IN : AuthStatus.LOGGED_IN;
});
});
}
void _onLoggedIn() {
widget.auth.getCurrentUser().then((user){
setState(() {
_userId = user.uid.toString();
});
});
setState(() {
authStatus = AuthStatus.LOGGED_IN;
});
}
void _onSignedOut() {
setState(() {
authStatus = AuthStatus.NOT_LOGGED_IN;
_userId = "";
});
}
Widget _buildWaitingScreen() {
return Scaffold(
body: Container(
alignment: Alignment.center,
child:
ColorLoader5(
dotOneColor: Colors.blueGrey[600],
dotTwoColor: Colors.blueGrey[700],
dotThreeColor: Colors.blueGrey[800],
dotType: DotType.circle,
dotIcon: Icon(Icons.adjust),
duration: Duration(seconds: 1),
),
),
);
}
#override
Widget build(BuildContext context) {
switch (authStatus) {
case AuthStatus.NOT_DETERMINED:
return _buildWaitingScreen();
break;
case AuthStatus.NOT_LOGGED_IN:
return new LoginScreen(
auth: widget.auth,
onSignedIn: _onLoggedIn,
);
break;
case AuthStatus.LOGGED_IN:
if (_userId.length > 0 && _userId != null) {
return new Container(child: SingleChildScrollView(child: LessonPage(
title: LESSON_PAGE_TITLE,
userId: _userId,
auth: widget.auth,
onSignedOut: _onSignedOut,
)));
} else return _buildWaitingScreen();
break;
default:
return _buildWaitingScreen();
}
}
}
Lesson Page:
class LessonPage extends StatefulWidget {
LessonPage({Key key, this.auth, this.userId, this.onSignedOut, this.title}) : super(key: key);
final String title;
final BaseAuth auth;
final VoidCallback onSignedOut;
final String userId;
#override
_LessonPageState createState() => _LessonPageState();
}
class _LessonPageState extends State<LessonPage> {
List lessons;
#override
void initState() {
lessons = StaticMethods.getLessons();
super.initState();
}
#override
Widget build(BuildContext context) {
ListTile makeListTile(Lesson lesson) => ListTile(
contentPadding:
EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
leading: Container(
padding: EdgeInsets.only(right: 12.0),
decoration: new BoxDecoration(
border: new Border(
right: new BorderSide(width: 1.0, color: Colors.white24))),
child: IconButton(
icon: Icon(Icons.file_download, color: Colors.white),
onPressed: (){},
),
),
title: Text(
lesson.title,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
subtitle: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: LinearProgressIndicator(
backgroundColor: Color.fromRGBO(209, 224, 224, 0.2),
value: lesson.indicatorValue,
valueColor: AlwaysStoppedAnimation(Colors.green)),
)),
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(lesson.level,
style: TextStyle(color: Colors.white))),
)
],
),
trailing:
Icon(Icons.keyboard_arrow_right, color: Colors.white, size: 30.0),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(lesson: lesson)));
},
);
Card makeCard(Lesson lesson) => Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(64, 75, 96, .9)),
child: makeListTile(lesson),
),
);
final makeBody = Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: lessons.length,
itemBuilder: (BuildContext context, int index) {
return makeCard(lessons[index]);
},
),
);
final makeBottom = Container(
height: 55.0,
child: BottomAppBar(
color: Color.fromRGBO(58, 66, 86, 1.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconButton(
icon: Icon(Icons.school, color: Colors.white),
onPressed: () => StaticMethods.goToWidget(context, new LessonPage(title: LESSON_PAGE_TITLE)),
),
IconButton(
icon: Icon(Icons.flight_takeoff, color: Colors.white),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.account_box, color: Colors.white),
onPressed: () {},
)
],
),
),
);
final topAppBar = AppBar(
elevation: 0.1,
backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
title: Text(widget.title),
automaticallyImplyLeading: false,
);
return Scaffold(
backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
appBar: topAppBar,
body: makeBody,
bottomNavigationBar: makeBottom,
);
}
}
LoginScreen Containers:
Widget OptionPage() {
return new Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Color.fromRGBO(58, 66, 86, 1.0),
image: DecorationImage(
colorFilter: new ColorFilter.mode(
Colors.black.withOpacity(0.1), BlendMode.dstATop),
image: AssetImage('assets/images/drones.jpg'),
fit: BoxFit.cover,
),
),
child: new Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 250.0),
child: Center(
child: Icon(
Icons.school,
color: Colors.white,
size: 40.0,
),
),
),
Container(
padding: EdgeInsets.only(top: 20.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
LOGIN_SCREEN_TITLE,
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
],
),
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 30.0, right: 30.0, top: 150.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new OutlineButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
color: Color.fromRGBO(58, 66, 86, 1.0),
highlightedBorderColor: Colors.white,
onPressed: () => gotoSignup(),
child: new Container(
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 20.0,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Text(
LOGIN_SCREEN_SIGN_UP,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
],
),
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 30.0, right: 30.0, top: 30.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
color: Colors.white,
onPressed: () => gotoLogin(),
child: new Container(
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 20.0,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Text(
LOGIN_SCREEN_LOGIN,
textAlign: TextAlign.center,
style: TextStyle(
color: Color.fromRGBO(58, 66, 86, 1.0),
fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
],
),
),
],
),
);
}
Widget LoginPage() {
return new Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.white,
image: DecorationImage(
colorFilter: new ColorFilter.mode(
Colors.black.withOpacity(0.05), BlendMode.dstATop),
image: AssetImage('assets/images/drones.jpg'),
fit: BoxFit.cover,
),
),
child: new Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(120.0),
child: Center(
child: Icon(
Icons.school,
color: Color.fromRGBO(58, 66, 86, 1.0),
size: 50.0,
),
),
),
new Row(
children: <Widget>[
new Expanded(
child: new Padding(
padding: const EdgeInsets.only(left: 40.0),
child: new Text(
LOGIN_SCREEN_EMAIL,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color.fromRGBO(58, 66, 86, 1.0),
fontSize: 15.0,
),
),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
child: TextFormField( // LOGIN SCREEN EMAIL
maxLines: 1,
keyboardType: TextInputType.emailAddress,
autofocus: false,
textAlign: TextAlign.left,
decoration: InputDecoration(
icon: Icon(Icons.alternate_email),
hintText: LOGIN_SCREEN_EMAIL_HINT,
hintStyle: TextStyle(color: Colors.grey),
),
validator: (value) => value.isEmpty ? LOGIN_SCREEN_EMAIL_WARNING : null,
onSaved: (value) => _email = value,
),
),
],
),
),
Divider(
height: 24.0,
color: Color(0x00000000),
),
new Row(
children: <Widget>[
new Expanded(
child: new Padding(
padding: const EdgeInsets.only(left: 40.0),
child: new Text(
LOGIN_SCREEN_PASSWORD,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color.fromRGBO(58, 66, 86, 1.0),
fontSize: 15.0,
),
),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
child: TextFormField( // LOGIN SCREEN PASSWORD
obscureText: true,
keyboardType: TextInputType.emailAddress,
maxLines: 1,
autofocus: false,
textAlign: TextAlign.left,
decoration: InputDecoration(
icon: Icon(Icons.lock_outline),
hintText: LOGIN_SCREEN_PASSWORD_HINT,
hintStyle: TextStyle(color: Colors.grey),
),
validator: (value) => value.isEmpty ? LOGIN_SCREEN_PASSWORD_WARNING : null,
onSaved: (value) => _password = value,
),
),
],
),
),
Divider(
height: 24.0,
color: Color(0x00000000),
),
new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: new FlatButton(
child: new Text(
LOGIN_SCREEN_FORGOT_PASSWORD,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color.fromRGBO(58, 66, 86, 1.0),
fontSize: 15.0,
),
textAlign: TextAlign.end,
),
onPressed: () => StaticMethods.locked(context),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 30.0, right: 30.0, top: 20.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton( // LOGIN SCREEN LOGIN BUTTON
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: Color.fromRGBO(58, 66, 86, 1.0),
onPressed: () => _validateAndSubmit(),
child: new Container(
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 20.0,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Text(
LOGIN_SCREEN_LOGIN,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
],
),
),
Divider(
height: 25.0,
color: Color(0x00000000),
),
_showErrorMessage(),
Divider(
height: 25.0,
color: Color(0x00000000),
),
_showLoading(),
],
),
);
}
Widget SignupPage() {
return new Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.white,
image: DecorationImage(
colorFilter: new ColorFilter.mode(
Colors.black.withOpacity(0.05), BlendMode.dstATop),
image: AssetImage('assets/images/drones.jpg'),
fit: BoxFit.cover,
),
),
child: new Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(100.0),
child: Center(
child: Icon(
Icons.school,
color: Color.fromRGBO(58, 66, 86, 1.0),
size: 50.0,
),
),
),
new Row(
children: <Widget>[
new Expanded(
child: new Padding(
padding: const EdgeInsets.only(left: 40.0),
child: new Text(
LOGIN_SCREEN_EMAIL,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color.fromRGBO(58, 66, 86, 1.0),
fontSize: 15.0,
),
),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
child: TextField( //SIGNUP SCREEN EMAIL
obscureText: true,
textAlign: TextAlign.left,
decoration: InputDecoration(
hintText: LOGIN_SCREEN_EMAIL_HINT,
hintStyle: TextStyle(color: Colors.grey),
),
),
),
],
),
),
Divider(
height: 24.0,
color: Color(0x00000000),
),
new Row(
children: <Widget>[
new Expanded(
child: new Padding(
padding: const EdgeInsets.only(left: 40.0),
child: new Text(
LOGIN_SCREEN_PASSWORD,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color.fromRGBO(58, 66, 86, 1.0),
fontSize: 15.0,
),
),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
child: TextField( // SIGNUP SCREEN PASSWORD
obscureText: true,
textAlign: TextAlign.left,
decoration: InputDecoration(
hintText: LOGIN_SCREEN_PASSWORD_HINT,
hintStyle: TextStyle(color: Colors.grey),
),
),
),
],
),
),
Divider(
height: 24.0,
color: Color(0x00000000),
),
new Row(
children: <Widget>[
new Expanded(
child: new Padding(
padding: const EdgeInsets.only(left: 40.0),
child: new Text( // SIGNUP SCREEN CONFIRM PASSWORD
LOGIN_SCREEN_CONFIRM_PASSWORD,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color.fromRGBO(58, 66, 86, 1.0),
fontSize: 15.0,
),
),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
child: TextField(
obscureText: true,
textAlign: TextAlign.left,
decoration: InputDecoration(
hintText: LOGIN_SCREEN_PASSWORD_HINT,
hintStyle: TextStyle(color: Colors.grey),
),
),
),
],
),
),
Divider(
height: 24.0,
color: Color(0x00000000),
),
new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: new FlatButton(
child: new Text(
LOGIN_SCREEN_HAVE_ACCOUNT,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color.fromRGBO(58, 66, 86, 1.0),
fontSize: 15.0,
),
textAlign: TextAlign.end,
),
onPressed: () => StaticMethods.locked(context),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 30.0, right: 30.0, top: 50.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton( // SIGNUP SCREEN SIGN UP BUTTON
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: Color.fromRGBO(58, 66, 86, 1.0),
onPressed: () => StaticMethods.locked(context),
child: new Container(
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 20.0,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Text(
LOGIN_SCREEN_SIGN_UP,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
],
),
),
],
),
);
}
PageController _controller = new PageController(initialPage: 1, viewportFraction: 1.0);
#override
Widget build(BuildContext context) {
_isIos = Theme.of(context).platform == TargetPlatform.iOS;
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: new Form (
key: _formKey,
child: PageView(
controller: _controller,
physics: new AlwaysScrollableScrollPhysics(),
children: <Widget>[LoginPage(), OptionPage(), SignupPage()],
scrollDirection: Axis.horizontal,
onPageChanged: (num){
switch (num) {
case 0:
setState(() {
_formKey.currentState.reset();
_errorMessage = "";
_formMode = FormMode.LOGIN;
});
break;
case 1:
setState(() {
_formKey.currentState.reset();
_errorMessage = "";
_formMode = FormMode.OPTIONS;
});
break;
case 2:
setState(() {
_formKey.currentState.reset();
_errorMessage = "";
_formMode = FormMode.SIGNUP;
});
break;
}
},
),
),
);
}
Error:
I/flutter (18510): The following assertion was thrown during performLayout():
I/flutter (18510): RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
.....
In the error, it shows just a blank page instead of lesson page, and checking firebase I can see that a user logs in so I think it is some layout issue.
What I've tried:
RootPage (I still saw a blank screen):
return new LessonPage(
title: LESSON_PAGE_TITLE,
userId: _userId,
auth: widget.auth,
onSignedOut: _onSignedOut,
);
I tried to return a normal page instead of lesson page which just shows a loading animation which is already tested and works but still I see a blank page:
return _buildWaitingScreen();
LessonPage (still see blank page):
Widget makeBody(BuildContext context) => Container(
height: MediaQuery.of(context).size.height / 1.5,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: lessons.length,
itemBuilder: (BuildContext context, int index) {
return makeCard(lessons[index]);
},
),
);
return Scaffold(
backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
appBar: topAppBar,
body: makeBody(context),
bottomNavigationBar: makeBottom,
);
You dont need Container and SingleChildScrollView in below snippet:
return LessonPage(
title: LESSON_PAGE_TITLE,
userId: _userId,
auth: widget.auth,
onSignedOut: _onSignedOut,
);
If that didn't fix,
RenderCustomMultiChildLayoutBox object was given an infinite size during layout. means that you have used ListView or ScrollView or any other widget that has infinite size. In order to prevent this issue, wrap your makeBody list view with fixed size. If it is working you can use MediaQuery.of(context).size.height(gives device screen width) and adjest the size you want.
Ex:
Widget makeBody(BuildContext context) => Container(
height: MediaQuery.of(context).size.height / 1.5,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: lessons.length,
itemBuilder: (BuildContext context, int index) {
return makeCard(lessons[index]);
},
),
);
and call the method: body: makeBody(context),
Fix in RootPage:
return new Container(
height: MediaQuery.of(context).size.height,
child: LessonPage(
title: LESSON_PAGE_TITLE,
userId: _userId,
auth: widget.auth,
onSignedOut: _onSignedOut,
)
);

How to change the orientation of on page in my app

I want to change the orientation of only one page within my app to landscape to view larger pictures
I can only find code to set orientation for the whole app. I don't know how to implement this( Flutter: How to set and lock screen orientation on-demand ) code into the existing code
// ======== CAROUSEL =========
return Scaffold(
appBar: AppBar(
backgroundColor: new Color(0xFFFA983A),
title: Image.asset(
'assets/images/logo_white.png',
fit: BoxFit.cover,
),
elevation: 0.0,
centerTitle: true,
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.search),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => new SearchPage()));
},
),
],
),
body: Column(
children: <Widget>[
Container(
alignment: Alignment.topCenter,
height: 200,
child: GestureDetector(
child: Hero(
tag: 'carouselHero',
child: SizedBox.expand(
child: Stack(
children: <Widget>[
imageSlider,
banner,
],
),
),
),
onDoubleTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return ImageScreen();
}));
},
),
),
SizedBox(height: 4),
Expanded(
child: Container(
padding: EdgeInsets.only(left: 12.0, top: 4.0, right: 12.0),
child: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
widget.propertyDetailTown,
style: TextStyle(
color: Color(0xFFFA983A),
fontSize: 20.0,
fontWeight: FontWeight.bold),
),
Text(
"Ref: RBD02548649",
style: TextStyle(
color: Colors.grey,
fontSize: 14.0,
fontWeight: FontWeight.normal),
),
],
),
SizedBox(
height: 4,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
widget.propertyDetailArea,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
Text(
widget.propertyDetailPrice,
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.normal,
color: Color(0xFFFA983A)),
),
],
),
SizedBox(
height: 8,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Image.asset(
'assets/images/icons/beds_new.png',
scale: 1.75,
),
Text(" 4"),
SizedBox(
width: 8,
),
Image.asset(
'assets/images/icons/bath_new.png',
scale: 1.75,
),
Text(
" 3",
),
SizedBox(
width: 8,
),
Image.asset(
'assets/images/icons/parking_new.png',
scale: 1.75,
),
Text(" 2"),
],
),
Text(
"1200 sqr ft.",
style: TextStyle(color: Colors.grey),
)
],
),
SizedBox(
height: 4,
),
Divider(
height: 10,
),
SizedBox(
height: 4,
),
// PROPERTY DESCRIPTION ==============================
Text(
'Description',
style: TextStyle(
color: Colors.black.withOpacity(0.8),
fontSize: 18.0,
fontWeight: FontWeight.bold),
),
Text(
"Lorem Ipsum is simply dummy text of the printing and typesetting "
"industry. Lorem Ipsum has been the industry's standard dummy "
"text ever since the 1500s, when an unknown printer took a "
"galley of type and scrambled it to make a type specimen book. "
"It has survived not only five centuries, but also the leap "
"into electronic typesetting, remaining essentially unchanged.",
style: TextStyle(
color: Colors.black.withOpacity(0.6),
fontSize: 16.0,
fontWeight: FontWeight.normal),
),
SizedBox(height: 8),
Divider(height: 10),
Text(
"AMENITIES",
style: TextStyle(
color: Colors.black.withOpacity(0.8),
fontSize: 18.0,
fontWeight: FontWeight.bold),
),
SizedBox(height: 8.0),
// AMENITIES STARTS HERE ===============================
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(
Icons.hotel,
color: Color(0xFFFA983A),
),
Text(
" One",
style: TextStyle(fontSize: 16),
),
SizedBox(width: 100.0),
Icon(
Icons.room,
color: Color(0xFFFA983A),
),
Text(" Two")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(
Icons.hotel,
color: Color(0xFFFA983A),
),
Text(
" One",
style: TextStyle(fontSize: 16),
),
SizedBox(width: 100.0),
Icon(
Icons.room,
color: Color(0xFFFA983A),
),
Text(" Two")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(
Icons.hotel,
color: Color(0xFFFA983A),
),
Text(
" One",
style: TextStyle(fontSize: 16),
),
SizedBox(width: 100.0),
Icon(
Icons.room,
color: Color(0xFFFA983A),
),
Text(" Two")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(
Icons.hotel,
color: Color(0xFFFA983A),
),
Text(
" One",
style: TextStyle(fontSize: 16),
),
SizedBox(width: 100.0),
Icon(
Icons.room,
color: Color(0xFFFA983A),
),
Text(" Two")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(
Icons.hotel,
color: Color(0xFFFA983A),
),
Text(
" One",
style: TextStyle(fontSize: 16),
),
SizedBox(width: 100.0),
Icon(
Icons.room,
color: Color(0xFFFA983A),
),
Text(" Two")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(
Icons.hotel,
color: Color(0xFFFA983A),
),
Text(
" One",
style: TextStyle(fontSize: 16),
),
SizedBox(width: 100.0),
Icon(
Icons.room,
color: Color(0xFFFA983A),
),
Text(" Two")
],
),
SizedBox(
height: 10,
),
Text(
"Home Loan Calculator",
style: TextStyle(
color: Colors.black.withOpacity(0.8),
fontSize: 18.0,
fontWeight: FontWeight.bold),
),
// Image.asset("assets/google_map.jpg"),
],
),
),
),
),
)
],
),
);
}
}
// ===========SECOND PAGE NEEDS TO BE LANDSCAPE ==================
class ImageScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
Widget imageSlider = Container(
height: MediaQuery.of(context).size.height,
child: Carousel(
boxFit: BoxFit.cover,
images: [
AssetImage('assets/images/houses/house.jpg'),
AssetImage('assets/images/houses/house1.jpg'),
AssetImage('assets/images/houses/house2.jpg'),
AssetImage('assets/images/houses/house3.jpg'),
AssetImage('assets/images/houses/house4.jpg'),
],
autoplay: false,
dotBgColor: Colors.transparent,
dotSize: 0,
),
);
return Scaffold(
body: GestureDetector(
child: Center(
child: Hero(
tag: 'carouselHero',
child: imageSlider,
),
),
onTap: () {
Navigator.pop(context);
},
),
);
}
}```
when i click on a picture it has to go to a new page which automatically change orientation to Landscape ans when i click back to previous page it changes again.
You are using a StatelessWidget, so you cannot override initState and dispose. First, convert your StatelessWidget to StatefulWidget, then implement the code provided by the other answer.
class ImageScreen extends StatefulWidget {
#override
ImageScreenState createState() => ImageScreenState();
}
class ImageScreenState extends State<ImageScreen> {
#override
void initState(){
super.initState();
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
]);
}
#override
dispose(){
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
super.dispose();
}
#override
Widget build(BuildContext context) {
Widget imageSlider = Container(
height: MediaQuery.of(context).size.height,
child: Carousel(
boxFit: BoxFit.cover,
images: [
AssetImage('assets/images/houses/house.jpg'),
AssetImage('assets/images/houses/house1.jpg'),
AssetImage('assets/images/houses/house2.jpg'),
AssetImage('assets/images/houses/house3.jpg'),
AssetImage('assets/images/houses/house4.jpg'),
],
autoplay: false,
dotBgColor: Colors.transparent,
dotSize: 0,
),
);
return Scaffold(
body: GestureDetector(
child: Center(
child: Hero(
tag: 'carouselHero',
child: imageSlider,
),
),
onTap: () {
Navigator.pop(context);
},
),
);
}
}

Adding a new column to a card in Flutter

How do I add a new column to a Card in flutter?
Currently, I have 2 Columns and can't figure out how to add a third between these since they are on the left and right sides. When I have tried adding a "new Column", it only creates a new row of text under the first Column.
This is my code so far:
Widget _buildListItem(BuildContext context, Record record) {
return Card(
key: ValueKey(record.activityName),
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(64, 75, 96, .9)),
child: ListTile(
contentPadding:
EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
title: Text(
record.activityName,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 23),
),
subtitle: Row(
children: <Widget>[
new Flexible(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
RichText(
text: TextSpan(
text: "Activations: "+record.activations+
"\n"+record.dateCompleted,
style: TextStyle(color: Colors.white),
),
maxLines: 2,
softWrap: true,
)
],
)
)
],
),
trailing: Container(
child: Hero(
tag: "avatar_" + record.activityName,
child: CircleAvatar(
radius: 32,
backgroundImage: NetworkImage(record.icon),
backgroundColor: Colors.white,
)
)
),
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => new DetailPage(record: record)));
}
),
)
);
}
I am wanting 3 columns so that I can add either an image in the middle of this card.
Current output
Expected output
Based on your screenshot, here is the solution. You can modify it according to your needs.
Widget _buildListItem(BuildContext context) {
return Card(
margin: EdgeInsets.all(12),
elevation: 4,
color: Color.fromRGBO(64, 75, 96, .9),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16),
child: Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("Jumping", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
SizedBox(height: 4),
Text("Activations 9", style: TextStyle(color: Colors.white70)),
Text("03-08-19", style: TextStyle(color: Colors.white70)),
],
),
Spacer(),
CircleAvatar(backgroundColor: Colors.white),
],
),
),
);
}
Output:

bottom overflowed by 42 pixels in a SingleChildScrollView

I have used a form inside a SingleChildScrollView, and everything works fine:
Form :
Everything works fine,
I have used this code
#override
Widget build(BuildContext context) {
double stackHeight = MediaQuery.of(context).size.height/4;
double width = MediaQuery.of(context).size.width;
return Scaffold(
body: SingleChildScrollView(
child :SafeArea(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [const Color(0xFF3023AE), const Color(0xFFC86DD7)])),
child: Column(
children: <Widget>[
Container(
height: stackHeight*2.6,
child: IntroViewsFlutter(
pages,
onTapDoneButton: (){
Navigator.pop(context);
},
showSkipButton: false,
pageButtonsColor: btnColors,
),
),
Container(
height: stackHeight*1.4,
child: bottomHomePage(),
color: pageColor,
width: width,
),
],
),
)
),
)
);
but when errors appear, this is what happens :
I have tried many things, I have heard about layoutBuilder, but dont know if it will work for me or there are another solutions that can adapt to runtime events.
UPDATE :
the problem was coming only of using an expanded inside a column : here we are the code again :
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: Center (
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [const Color(0xFF3023AE), const Color(0xFFC86DD7)])),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 70.0, bottom: 20.0),
child: Text(
"C'est parti !",
style: TextStyle(fontSize: 32, color: Colors.white),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Container(
width: width_textFormField + 15.0,
child: Text(
" Avant de commencer, sache que pour utiliser pleinement ta BanKids tu devras demander à tes parents de s'inscrire pour te débloquer toutes les fonctionnalités",
style: TextStyle(
fontSize: 14,
color: Colors.white,
),
textAlign: TextAlign.center,
)),
),
Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
child: Text(
"Client Bank ?",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
Container(
child: Row(
children: <Widget>[
Text(
"Oui",
style: TextStyle(color: Colors.white),
),
Radio(
value: 1,
activeColor: Colors.white,
groupValue: _grpVal,
onChanged: _handleRadioValueChange1,
),
],
)),
Container(
child: Row(
children: <Widget>[
Text(
"Non",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
Radio(
activeColor: Colors.white,
value: 2,
groupValue: _grpVal,
onChanged: _handleRadioValueChange1,
),
],
)),
],
)),
Container(
child: Column(
children: <Widget>[
customizedTextFormField(
hintText: "Nom",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Prénom",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Date de Naissance",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "CIN",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Email",
width: width_textFormField + 10.0,
txtColor: Colors.black)
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
width: width_textFormField,
child: Row(
children: <Widget>[
Checkbox(
checkColor: Color(0xFF3023AE),
value: isCheck,
activeColor: Colors.white,
onChanged: _handleCheckBox,
),
Expanded(
child: Text(
"En continuant l'inscription, je déclare accepter ces conditions d'utilisations ",
style: TextStyle(color: Colors.white),
),
),
],
),
),
),
//************ next work
Container(
width: 200,
height: 60,
margin: EdgeInsets.only(right: 8.0,bottom: 8.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
Button_with_icon(
backgroundColor: Color(0xFF7CB342),
textColor: Colors.white,
textButton: "Continuer",
onPressed: (){
if(_formKey.currentState.validate()){
print("say l3adab");
}
},
icon: Icon(Icons.arrow_forward_ios),
),
],
)
),
],
),
)),
),
)
),
);
The problem was only of using an expanded inside my form, so I have removed and removed the height and width that I have given to my container :
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: Center (
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [const Color(0xFF3023AE), const Color(0xFFC86DD7)])),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 70.0, bottom: 20.0),
child: Text(
"C'est parti !",
style: TextStyle(fontSize: 32, color: Colors.white),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Container(
width: width_textFormField + 15.0,
child: Text(
" Avant de commencer, sache que pour utiliser pleinement ta BanKids tu devras demander à tes parents de s'inscrire pour te débloquer toutes les fonctionnalités",
style: TextStyle(
fontSize: 14,
color: Colors.white,
),
textAlign: TextAlign.center,
)),
),
Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
child: Text(
"Client Bank ?",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
Container(
child: Row(
children: <Widget>[
Text(
"Oui",
style: TextStyle(color: Colors.white),
),
Radio(
value: 1,
activeColor: Colors.white,
groupValue: _grpVal,
onChanged: _handleRadioValueChange1,
),
],
)),
Container(
child: Row(
children: <Widget>[
Text(
"Non",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
Radio(
activeColor: Colors.white,
value: 2,
groupValue: _grpVal,
onChanged: _handleRadioValueChange1,
),
],
)),
],
)),
Container(
child: Column(
children: <Widget>[
customizedTextFormField(
hintText: "Nom",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Prénom",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Date de Naissance",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "CIN",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Email",
width: width_textFormField + 10.0,
txtColor: Colors.black)
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
width: width_textFormField,
child: Row(
children: <Widget>[
Checkbox(
checkColor: Color(0xFF3023AE),
value: isCheck,
activeColor: Colors.white,
onChanged: _handleCheckBox,
),
Expanded(
child: Text(
"En continuant l'inscription, je déclare accepter ces conditions d'utilisations ",
style: TextStyle(color: Colors.white),
),
),
],
),
),
),
//************ next work
Container(
width: 200,
height: 60,
margin: EdgeInsets.only(right: 8.0,bottom: 8.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
Button_with_icon(
backgroundColor: Color(0xFF7CB342),
textColor: Colors.white,
textButton: "Continuer",
onPressed: (){
if(_formKey.currentState.validate()){
print("say l3adab");
}
},
icon: Icon(Icons.arrow_forward_ios),
),
],
)
),
],
),
)),
),
)
),
);
put a column child on singlechildscrollview then create a row for each form element, and put those in expanded widget
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Material(
elevation: 0,
child: Container(
padding: EdgeInsets.all(16),
child: Column(
children: <Widget>[
Column(
children: <Widget>[
Form(
onChanged: () {
_tcFormKey.currentState.validate();
if (_tcController.text.length != 11) {
setState(() {
tcValidated = false;
});
}
},
key: _tcFormKey,
child: TextFormField(
controller: _tcController,
maxLength: 11,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly,
],
validator: (String value) {
if (value.isEmpty) {
return 'Zorunlu alan';
}
if (value.length != 11) {
return 'Kimlik numarası 11 haneli olmalıdır';
}
if (value.length == 11 && !Functions.validateTC(value.toString())) {
return 'Hatalı TC. Kimlik No';
} else {
setState(() {
tcValidated = true;
});
}
},
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(
counterText: '',
suffixIcon: tcValidated
? Icon(
Icons.check,
color: Colors.green,
)
: Text(''),
labelText: 'TC Kimlik No',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black26, width: 1),
),
),
),
),
SizedBox(
height: 12,
),
Form(
onChanged: () {
_uavtFormKey.currentState.validate();
},
key: _uavtFormKey,
child: TextFormField(
controller: _uavtController,
maxLength: 11,
inputFormatters: <TextInputFormatter>[WhitelistingTextInputFormatter.digitsOnly],
validator: (String value) {
if (value.isEmpty) {
return 'Zorunlu alan';
}
},
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(
labelText: 'UAVT Adres Kodu',
suffixIcon: Icon(Icons.location_on),
counterText: '',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black26, width: 1),
),
),
),
),
SizedBox(
height: 12,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Form(
onChanged: () {
_adFormKey.currentState.validate();
},
key: _adFormKey,
child: TextFormField(
controller: _adController,
maxLength: 64,
validator: (String value) {
if (value.isEmpty) {
return 'Zorunlu alan';
}
},
inputFormatters: [
WhitelistingTextInputFormatter(
RegExp("[a-zA-ZĞğÜüÖöŞşçÇİı]"),
),
],
decoration: InputDecoration(
labelText: 'Ad',
counterText: '',
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blue,
width: 1,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black26,
width: 1,
),
),
),
),
),
),
SizedBox(
width: 8,
),
Expanded(
child: Form(
onChanged: () {
_soyadFormKey.currentState.validate();
},
key: _soyadFormKey,
child: TextFormField(
controller: _soyadController,
maxLength: 64,
validator: (String value) {
if (value.isEmpty) {
return 'Zorunlu alan';
}
},
inputFormatters: [
WhitelistingTextInputFormatter(
RegExp("[a-zA-ZĞğÜüÖöŞşçÇİı]"),
),
],
decoration: InputDecoration(
labelText: 'Soyad',
counterText: '',
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blue,
width: 1,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black26,
width: 1,
),
),
),
),
),
),
],
),
SizedBox(
height: 12,
),
Form(
onChanged: () {
_telFormKey.currentState.validate();
},
key: _telFormKey,
child: TextFormField(
controller: _telController,
maxLength: 10,
validator: (String val) {
if (val.isEmpty) {
return 'Zorunlu alan';
}
},
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly,
],
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(
errorStyle: TextStyle(color: Colors.red),
hintText: '10 Haneli Telefon Numarası',
labelText: 'Telefon Numarası',
hintStyle: TextStyle(color: Colors.black38),
suffixIcon: Icon(Icons.phone_iphone),
counterText: '',
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blue,
width: 1,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black26,
width: 1,
),
),
),
),
),
SizedBox(
height: 12,
),
OutlineButton(
highlightColor: Colors.transparent,
splashColor: Colors.blue.shade50,
shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(2)),
borderSide: BorderSide(color: !emptyDateError ? Colors.black26 : Colors.red),
onPressed: () {
selectedBDate = '';
DatePicker.showDatePicker(context,
showTitleActions: true,
minTime: DateTime(1910, 1, 1),
maxTime: DateTime.now(),
onChanged: (date) {}, onConfirm: (date) {
int y = int.parse(DateFormat.y().format(date));
int m = int.parse(DateFormat.M().format(date));
int d = int.parse(DateFormat.d().format(date));
setState(() {
selectedBDate = '$y-$m-$d';
emptyDateError = false;
});
print('confirm $date');
}, currentTime: DateTime.now(), locale: LocaleType.tr);
},
child: Padding(
padding: const EdgeInsets.only(left: 2, right: 2, top: 16, bottom: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Icon(Icons.calendar_today, size: 16,),
Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(
' Doğum Tarihi',
style: TextStyle(fontSize: 15),
),
),
],
),
),
selectedBDate != ''
? Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Text('$selectedBDate'),
),
)
: emptyDateError
? Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Text(
'Zorunlu Alan',
style: TextStyle(color: Colors.red),
),
),
)
: Container(),
],
),
),
),
SizedBox(
height: 12,
),
Form(
onChanged: () {
_mailFormKey.currentState.validate();
},
key: _mailFormKey,
child: TextFormField(
controller: _mailController,
validator: (String val) {
if (val.isEmpty) {
return 'Zorunlu alan';
}
if(!Functions.isEmail(val)){
return 'Geçerli bir mail adresi belirtiniz';
}
},
decoration: InputDecoration(
suffixIcon: Icon(Icons.mail_outline),
labelText: 'Mail Adresi',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black26, width: 1),
),
),
),
),
SizedBox(
height: 12,
),
Material(
elevation: 8,
shadowColor: Colors.green,
borderRadius: BorderRadius.circular(4),
color: Colors.green,
child: InkWell(
onTap: () {
if (_tcController.text != '' &&
_uavtController.text != '' &&
_adController.text != '' &&
_soyadController.text != '' &&
_telController.text != '' &&
_mailController.text != '' &&
selectedBDate != '' &&
Functions.validateTC(_tcController.text)) {
_tcFormKey.currentState.validate();
_uavtFormKey.currentState.validate();
_adFormKey.currentState.validate();
_soyadFormKey.currentState.validate();
_telFormKey.currentState.validate();
_mailFormKey.currentState.validate();
print(_telController.text.length);
var oprt = _telController.text.trim().split(' ')[0];
oprt = oprt.replaceAll('(', '');
oprt = oprt.replaceAll(')', '');
print(oprt);
_pageController.nextPage(duration: Duration(milliseconds: 300), curve: Curves.ease);
} else {
if (selectedBDate == '') {
setState(() {
emptyDateError = true;
});
}
_tcFormKey.currentState.validate();
_uavtFormKey.currentState.validate();
_adFormKey.currentState.validate();
_soyadFormKey.currentState.validate();
_telFormKey.currentState.validate();
_mailFormKey.currentState.validate();
}
},
child: Container(
width: double.infinity,
height: 48,
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'İlerle ',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white, fontSize: 18),
),
Icon(
Icons.arrow_forward,
color: Colors.white,
),
],
),
),
),
),
),
],
),
],
),
),
),
),

How to align two buttons at the bottom of the Dialog in Flutter

Here's a mockup of the dialog I'm trying to create in Flutter:
Here's what I have so far:
I'm unable to position my two button's with rounded bottom corners at the bottom of the dialog so that it looks like in the mockup.
I was able to make those buttons fit within the Dialog width, without the stack, but then it would be positioned at the top.
Here's the code for the dialog:
SimpleDialog carDialog = SimpleDialog(
contentPadding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
children: <Widget>[
Container(
height: 400,
child: Stack(
children: <Widget>[
Positioned(
bottom: 0,
child: IntrinsicWidth(
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(6)),
color: Colors.lightBlueAccent,
),
height: 45,
child: Center(
child: Text(
allTranslations.text('wait_enroute').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(6)),
color: AppColors.action_button,
),
height: 45,
child: Center(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
allTranslations.text('new_order').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
),
],
),
),
),
],
),
),
],
);
showDialog(context: context, builder: (context) => carDialog);
I have found a working solution. It does not require the Stack widget, everything can be nested within a Column like so:
SimpleDialog carDialog = SimpleDialog(
contentPadding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 400,
),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: InkWell(
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.only(bottomLeft: Radius.circular(6)),
color: Colors.lightBlueAccent,
),
height: 45,
child: Center(
child: Text(
allTranslations.text('wait_enroute').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.only(bottomRight: Radius.circular(6)),
color: AppColors.action_button,
),
height: 45,
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
allTranslations.text('new_order').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
),
],
),
],
),
],
);
showDialog(context: context, builder: (context) => carDialog);
The result:
You can try this replacing with Row
LayoutBuilder(
builder:(BuildContext context, BoxConstraints constraints){
return Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
width : constraints.maxWidth/2
child:Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(6)),
color: Colors.lightBlueAccent,
),
height: 45,
child: Center(
child: Text(
allTranslations.text('wait_enroute').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
SizedBox(
width : constraints.maxWidth/2
child:Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(6)),
color: AppColors.action_button,
),
height: 45,
child: Center(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
allTranslations.text('new_order').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
),
],
);
}
),

Resources