I'm trying to recreate this search input but I'm having troubles in keeping it that small, if I add the prefixIcon the height increases and I can't seem to control it.
Here's what I have right now.
I'm using a row because I will need to add a button after the input field as well, but that's for later.
Widget _buildSearch() => Container(
padding: EdgeInsets.all(8.0),
color: Color(0xFF131313),
height: 50.0,
child: Row(
children: <Widget>[
Flexible(
flex: 2,
child: TextFormField(
textAlign: TextAlign.left,
style: TextStyle(fontSize: 11.0),
decoration: InputDecoration(
contentPadding: new EdgeInsets.symmetric(vertical: 0.0),
border: InputBorder.none,
prefixIcon: Padding(
padding: EdgeInsets.all(0.0),
child: Icon(
Icons.search,
color: Colors.grey,
), // icon is 48px widget.
),
hintText: 'Search artist, genre, playlist',
hintStyle: TextStyle(fontSize: 11.0)),
),
),
],
),
);
adjust the content padding for the textfield and wrap your icon in padding widget since its input type is Widget
TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: 20), // add padding to adjust text
isDense: true,
hintText: "Email",
prefixIcon: Padding(
padding: EdgeInsets.only(top: 15), // add padding to adjust icon
child: Icon(Icons.help_outline),
),
);
this is the output of above code
you can adjust image size like this
prefixIcon: new Padding(
padding: const EdgeInsets.only( top: 15, left: 5, right: 0, bottom: 15),
child: new SizedBox(
height: 4,
child: Image.asset(imgname),
),
),
You can add height to your hintStyle to avoid this:
hintStyle: TextStyle(fontSize: 11.0, color: Colors.white, height: 3),
About height in TextStyle:
The height of this text span, as a multiple of the font size.
When height is null or omitted, the line height will be determined by
the font's metrics directly, which may differ from the fontSize. When
height is non-null, the line height of the span of text will be a
multiple of fontSize and be exactly fontSize * height logical pixels
tall.
You can use ListTile, the icon put in leading and TextFormField put in Title.
You can use like this
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top:20),
border: InputBorder.none,
hintStyle: TextStyle(
fontFamily: AppTheme.fontName,
fontWeight: FontWeight.w600,
fontSize: 16,
color: AppTheme.deactivatedText,
),
Do not use the prefixIcon property if you wanna controll the details, it's not useful.
This is what i do:
Container(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
height: 50.0,
color: const Color(0xff131313),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(0.0),
child: Icon(
Icons.search,
color: Colors.grey,
),
),
Flexible(
child: TextFormField(
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(0.0),
hintText: 'Search artist, genre, playlist',
hintStyle: TextStyle(
color: Colors.white,
fontSize: 11.0,
),
border: InputBorder.none,
),
style: TextStyle(
color: Colors.white,
fontSize: 11.0,
),
),
),
],
),
),
The first one is from my code, and the second one from yours. You can change the paddings as you like.
Use this method i think u like it,
you just have to add the FocusNode and controller by urself...
Padding(
padding: EdgeInsets.only(
left: parentWidth * .04,
right: parentWidth * .04,
top: parentHeight * .02,
bottom: parentHeight * .02),
child: Container(
padding: EdgeInsets.only(
left: parentWidth * .05, right: parentWidth * .05),
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.all(new Radius.circular(25.0))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
child: TextFormField(
focusNode: _searchingFocus,
textCapitalization: TextCapitalization.words,
controller: _searchController,
obscureText: false,
onFieldSubmitted: (term) {
_searchingFocus.unfocus();
},
// controller: _isSearching,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(0.0),
border: InputBorder.none,
hintText: StringEn.ALL_CATEGORY_TEXT,
hintStyle: new TextStyle(
color: CommonColor.MENU_BTN_COLOR.withOpacity(.4),
fontSize: categoryText - 4,
fontFamily: CommonWidget.AVENIR_BOOK)),
style: new TextStyle(
color: CommonColor.MENU_BTN_COLOR,
fontSize: categoryText - 3,
fontFamily: CommonWidget.AVENIR_BOOK),
),
),
Padding(
padding: new EdgeInsets.only(left: parentWidth * 0.0),
child: new Icon(
Icons.search,
color: Colors.grey,
size: parentWidth * 0.06,
),
),
],
),
),
),
Related
I nested my TextField inside a Container with width 10.0, but the textfield is still taking up the whole width of the device.
Widget _reviewBody() {
return SliverToBoxAdapter(
child: Container(
width: 10.0,
padding: EdgeInsets.only(bottom: 30.0),
child: TextField(
onChanged: (text) {
setState(() {
reviewBody = text;
});
},
keyboardType: TextInputType.multiline,
maxLines: null,
decoration: InputDecoration(
hintText: 'Add your thoughts here',
hintStyle: TextStyle(color: Burnt.hintTextColor),
enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Burnt.lightGrey)),
focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Burnt.primaryLight, width: 1.0)),
),
textAlign: TextAlign.center,
),
),
);
}
How do I set the TextField width?
Edit: Turns out SliverToBoxAdapter does magic, so I've used media query to set a padding on my container. Maybe I'm not supposed to use SliverToBoxAdatper, if someone can explain the right thing to do that would be great thanks.
Edit2: Actually I came up with an even better idea, I just put my Container inside a Row and made the Row center my 100.0 wide Container
I tried something like this
Container(
margin: EdgeInsets.only(top: 30, left: 30, right: 30),
width: MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
TextField(
decoration: InputDecoration(
hintText: "Inserisci la tua email",
hintStyle: TextStyle(fontSize: 20),
labelText: "Email",
labelStyle: TextStyle(
color: Utils.blackColor, fontSize: 20),
border: UnderlineInputBorder(
borderSide: BorderSide(color: Utils.greyColor)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.grey,
style: BorderStyle.solid))),
controller: nameController,
style: TextStyle(fontSize: 23)),
Padding(padding: EdgeInsets.only(top: 20)),
],
),
),
pu textfield and a container in a column as a child, then wrap children with flexible widget give them flex property
Basically I have a login page where I first segement into 2 container with one covers 55% and 45% of the screen. Then on top of these 2 container I add one more container with top 40% of the screen size and in it I have one more container which hold my user name and password text field. So on the design wise I am ok.
Now the issue when the keyboard comes the password field is totally not visible. First I just had stack then I did google and some suggest to put the Scaffold and add this line resizeToAvoidBottomPadding: false, but seems does not work for me either too.
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
body: Container(
child: Stack(
children: <Widget>[
// The containers in the background
new Column(
children: <Widget>[
new Container(
height: MediaQuery.of(context).size.height * .55,
//color: Colors.blue,
decoration: new BoxDecoration(
image: new DecorationImage(image: new AssetImage("lib/assets/cbg.png"), fit: BoxFit.cover,),
),
),
new Container(
height: MediaQuery.of(context).size.height * .45,
color: Colors.white,
)
],
),
// The card widget with top padding,
// incase if you wanted bottom padding to work,
// set the `alignment` of container to Alignment.bottomCenter
new Container(
alignment: Alignment.topCenter,
padding: new EdgeInsets.only(
top: MediaQuery.of(context).size.height * .40,
right: 20.0,
left: 20.0),
child: new Container(
height: MediaQuery.of(context).size.height * .45,
width: MediaQuery.of(context).size.width,
child: new Card(
color: Colors.white,
elevation: 4.0,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
children: <Widget>[
SizedBox(height: MediaQuery.of(context).size.height * .05),
new TextFormField(
decoration: new InputDecoration(
labelText: "Enter Email",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(10.0),
borderSide: new BorderSide(
color: Colors.blue
),
),
//fillColor: Colors.green
),
validator: (val) {
if(val.length==0) {
return "Email cannot be empty";
}else{
return null;
}
},
keyboardType: TextInputType.emailAddress,
style: new TextStyle(
fontFamily: "Poppins",
),
),
SizedBox(height: MediaQuery.of(context).size.height * .05),
new TextFormField(
decoration: new InputDecoration(
labelText: "Enter Password",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(10.0),
borderSide: new BorderSide(
),
),
//fillColor: Colors.green
),
validator: (val) {
if(val.length==0) {
return "Password cannot be empty";
}else{
return null;
}
},
keyboardType: TextInputType.emailAddress,
style: new TextStyle(
fontFamily: "Poppins",
),
),
],
),
)
),
),
),
new Container(
alignment: Alignment.topCenter,
padding: new EdgeInsets.only(
top: MediaQuery.of(context).size.height * .80,
right: 50.0,
left: 50.0),
child: new FlatButton(
color: Colors.red,
child: Text("Press Me"),
onPressed: () {},
),
),
new Container(
alignment: Alignment.topCenter,
padding: new EdgeInsets.only(
top: MediaQuery.of(context).size.height * .90,
right: 50.0,
left: 50.0),
child: new FlatButton(
color: Colors.red,
child: Text("Forgot Password ?"),
onPressed: () {},
),
)
],
)
)
);
}
}
After the changes the keyboard still appear a slight covering the textfield.
Can I achieve some
You should put all this inside a ListView, then when you open the keyboard the list will scroll up.
I'm 2 years late on this and you might find the solution already, but this is for someone who struggle to find the solution. (Include myself a couple a days ago)
To solve this, The "TextFormField" widget need another attribute called "scrollPadding".
TextFormField(
controller: controller,
scrollPadding: EdgeInsets.only(bottom:40), // THIS SHOULD SOLVE YOUR PROBLEM
decoration: InputDecoration(
labelText: title,
hintText: title,
filled: true,
fillColor: Colors.white,
enabledBorder: const OutlineInputBorder(
borderSide: const BorderSide(color: Colors.grey, width: 1.0),
),
border: const OutlineInputBorder(),
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return title;
}
return null;
},
),
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"),
),
],
)
],
),
),
)
],
),
i have an edit text and icon .. and i want a line under them .. so i added a divider after them like this:
new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Image.asset(
'assets/sa-logo.png',
width: 20.0,
height: 13.0,
),
Padding(
padding: EdgeInsets.only(left: 5.0, right: 5.0),
child: new Text(
'+966',
style: TextStyle(
fontSize: 15.0, color: Colors.grey),
),
),
new Flexible(
child: new TextField(
style: new TextStyle(
fontSize: 20.0,
color: Colors.black,
),
decoration: new InputDecoration(
border: InputBorder.none,
hintText: '5xxxxxxxx',
hintStyle: new TextStyle(
fontSize: 20.0,
),
),
keyboardType: TextInputType.number,
onChanged: (String value) {
this._data.phone = value;
setState(() {
phonelength = value.length;
done();
});
}),
),
],
),
Divider()
],
),
but the space between the line and the other widgets is big as shown:
how to make it smaller?
I just added this to the TextField:
contentPadding: EdgeInsets.symmetric(vertical: 0),
and that solved the problem.
I am using BottomNavigationBarItem to display bottom navigation UI with icons and text. I would like to be able to add badges with numeric values on those. Here is my current attempt:
bottomNavigationBar:
new BottomNavigationBar(items: <BottomNavigationBarItem>[
new BottomNavigationBarItem(
icon: new Stack(
children: <Widget>[
const Icon(Icons.home),
new Positioned(
top: 0.0,
left: 0.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(4.0),
color: Colors.red),
width: 16.0,
child: new Text(
"12",
style: const TextStyle(color: Colors.white),
),
))
],
),
title: new Text("Home")),
new BottomNavigationBarItem(
icon: const Icon(Icons.star), title: new Text("Star")),
],
type: BottomNavigationBarType.fixed),
However, the badge is positioned with the icon's bounding box, so it overlaps heavily with the icon:
What I would like, instead, is something like that:
Is it possible to achieve this using the BottomNavigationBarItem widget? If not, what would be a good workaround?
make sure that the badge position is right, and the overflowing children should be visible
icon: new Stack(
overflow: Overflow.visible,
children: <Widget>[
const Icon(Icons.home),
new Positioned(
top: -1.0,
right: -6.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(4.0), color: Colors.red),
width: 16.0,
child: new Text(
"12",
style: const TextStyle(color: Colors.white),
),
))
],
),
If it is useful to anyone, I made one that works in the AppBar.
static Widget makeIconWithBadge(String badgeText, GestureTapCallback onTap) {
return Container(
padding: EdgeInsets.only(right: 16.0),
child: Center(
child: new Stack(
overflow: Overflow.visible,
children: <Widget>[
const Icon(Icons.inbox),
new Positioned(
top: -6.0,
right: -6.0,
child: Container(
padding: EdgeInsets.all(2.0),
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(99.0),
color: Colors.white,
),
child: new Container(
padding: EdgeInsets.symmetric(vertical: 1.0, horizontal: 4.0),
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(99.0),
color: Colors.red),
child: Center(
child: new Text(
"12",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white, fontSize: 12.0,),
),
),
),
),
),
Positioned.fill(
child: Material(
borderRadius: BorderRadius.all(Radius.circular(99.0)),
color: Colors.transparent,
child: InkWell(onTap: onTap),
),
)
],
),
),
);
}