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,)
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],
),
)
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"),
),
],
)
],
),
),
)
],
),
UI stutters whenever CupertinoDatePicker is rotated due to using the picker in a FormField and calling formFieldState.didChange() on the picker's onDateTimeChanged
I'm trying to use Cupertino input fields in my app.
I've followed the steps in the Flutter Gallery to use CupertinoDatePicker. However, I'm wrapping the input fields inside a Form for validation.
This works, as I was able to tie the state of the picker to the FormFieldState. However, UI performance is abysmal. Every time the picker is rotated, I experience stutters. This is due to continuous call of state.didChange() on onDateTimeChanged
I tried calling state.didChange() only after the modal popup was dismissed, and it got rid of the stutters. But I want the state of the FormField to update as the user spins the picker.
Here's my code snippet.
Widget _getCupertinoDateTimeFormField(FormFieldState<DateTime> state) {
return GestureDetector(
onTap: () async {
await showCupertinoModalPopup<void>(
context: state.context,
builder: (BuildContext context) {
return _buildBottomPicker(
CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
initialDateTime: state.value?? DateTime.now(),
onDateTimeChanged: (DateTime newDateTime) {
state.didChange(newDateTime);
},
)
);
},
);
},
child: cupertinoDecoration(state, description,
Text(
_formatUI(state.value),
style: const TextStyle(color: CupertinoColors.inactiveGray),
),
),
);
}
Widget _buildBottomPicker(Widget picker) {
return Container(
height: _kPickerSheetHeight,
padding: const EdgeInsets.only(top: 6.0),
color: CupertinoColors.white,
child: DefaultTextStyle(
style: const TextStyle(
color: CupertinoColors.black,
fontSize: 22.0,
),
child: GestureDetector(
// Blocks taps from propagating to the modal sheet and popping.
onTap: () {},
child: SafeArea(
top: false,
child: picker,
),
),
),
);
}
Widget cupertinoDecoration <T> (FormFieldState<T> state, String description, Widget field) {
bool isError = state.errorText != null;
Widget label = Padding(
padding: EdgeInsets.symmetric(vertical: 1.0),
child: Text(
description,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 14.0,
color: CupertinoColors.black,
),
),
);
List<Widget> fieldWidgets = [label, field];
if (isError) {
// add our error message
fieldWidgets.add(Text(
state.errorText,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: CupertinoColors.destructiveRed,
fontSize: 12.0,
),
));
}
return Container(
decoration: const BoxDecoration(
color: CupertinoColors.white,
border: Border(
bottom: BorderSide(
color: CupertinoColors.inactiveGray, width: 0.0),
),
),
child: Padding(
padding:
const EdgeInsets.all(6.0),
child: SafeArea(
top: false,
bottom: false,
child: DefaultTextStyle(
style: const TextStyle(
letterSpacing: -0.24,
fontSize: 17.0,
color: CupertinoColors.black,
),
child: Align(
alignment: Alignment.centerLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: fieldWidgets,
),
),
),
),
),
);
}
Am I out of luck here? Are we not supposed to link the state of the picker to the state of the FormField?
Thanks in advance!
Trying to accomplish the below effect:
This is the code I have:
new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Divider(
color: const Color(0xFF000000),
height: 20
),
new Text(
"OR",
style: new TextStyle(
fontSize: 20.0,
color: const Color(0xFF000000),
fontWeight: FontWeight.w200,
),
),
const Divider(
color: const Color(0xFF000000),
height: 20
),
]),
The word OR appears in the middle but both Dividers are hidden? (However, if I play with the height you can see the height of the row increase/decrease but still no divider. How can I get this effect?
use this widget, it will do exactly what you want
class OrComponent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: Container(
height: 2.0,
color: AppColor.lighterGrey,
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 3.0),
child: Text("OR",style:TextStyle(color:Colors.black)),
),
Expanded(
child: Container(
height: 2.0,
color: Colors.grey,
),
),
],
);
}
}
You can use the Expanded widget on the two Dividers (and on the Text for coherence purposes)
Expanded(
flex: 1,
child: Divider(
color: const Color(0xFF000000),
height: 2,
)),
Expanded(
flex: 0,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 15.0),
child: Text(
"OR",
style: new TextStyle(
fontSize: 20.0,
color: const Color(0xFF000000),
fontWeight: FontWeight.w200,
),
))),
Expanded(
flex: 1,
child: Divider(
color: const Color(0xFF000000),
height: 2,
))
Map item;
List data;
Future getdata() async{
http.Response response= await http.get(Uri.encodeFull("https://talaikis.com/api/quotes/"));
item=json.decode(response.body);
setState(() {
data=item["quotes"];
});
debugPrint(data.toString());
}
I want to display this request in stateful widget which is like this
#override
Widget build(BuildContext context) {
return new Scaffold(
drawer: drawerLeft(),
appBar: AppBar(
title: Text(
"IN TIME",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w700),
),
backgroundColor: clr,
elevation: 0.0,
leading: MaterialButton(
child: Icon(
Icons.view_headline,
color: Colors.black,
),
onPressed: () {
scaffoldKey.currentState.openDrawer();
},
)),
key: scaffoldKey,
body: AnimatedContainer(
padding: EdgeInsets.only(top: 50.0),
duration: Duration(milliseconds: 1000),
curve: Curves.ease,
color: clr,
child: PageView.builder(
itemCount: 7, //7days
onPageChanged: (int page) {
this.setState(() {
Random rnd;
rnd = new Random();
int r = 0 + rnd.nextInt(_colors.length - 0);
clr = _colors[r];
});
},
controller: pageViewController,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Stack(
children: <Widget>[
Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: Colors.white,
),
height:
MediaQuery.of(scaffoldKey.currentContext).size.height -
150.0,
width:
MediaQuery.of(scaffoldKey.currentContext).size.width -
20.0,
child: Stack(
children: <Widget>[
Positioned(
width: MediaQuery.of(scaffoldKey.currentContext)
.size
.width -
100.0,
left: index != currentPage
? getMappedValue(20.0, 100.0, 160.0, 20.0, pos)
: getMappedValue(20.0, 100.0, 20.0, -120.0, pos),
top: 20.0,
child: Opacity(
opacity: index != currentPage
? getMappedValue(20.0, 100.0, 0.0, 01.0, pos)
: getMappedValue(20.0, 100.0, 01.0, 00.0, pos),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
_days[index],
maxLines: 1,
softWrap: true,
style: TextStyle(
color: Colors.deepOrange,
fontSize: 22.0,
fontWeight: FontWeight.w600),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 15.0),
child: Text(
'Quote for the day',
softWrap: true,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w300),
),
),
],
),
),
),
],
),
),
],
),
);
},
),
),
);
}
}
*Please help me out *
If I understand, you want to display the quotes under some padding that are being retrieved to your List which I'll assume to be an inferenced List<String>. If so, you could just use a ListView within your widget tree to display every fetched item in that list, like so:
(...)
data != null
? Padding(
padding: const EdgeInsets.only(top: 15.0),
child: ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(data[index]),
);
},
),
)
: Container(),
(...)