How to use a responsive text form field widget in flutter? - flutter

I'm using "maxLine" as a length for the text form field but it does not fit in different size of phones, what should I put in order to make the length responsive.
The box border should fit on the size of the phone. https://i.stack.imgur.com/Wisa6.png. Here's my code, I'm using onTap in gesture detector to call that widget
Widget buildDescription() => TextFormField(
maxLines: MediaQuery.of(context).size.height.toInt(),
initialValue: widget.description,
style: TextStyle(color: Colors.black, fontSize: 18),
decoration: InputDecoration(
hintText: 'Tell us what you feel',
hintStyle: TextStyle(color: Colors.black54),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
borderSide: BorderSide(
color: Colors.grey.shade500,
width: 2,
style: BorderStyle.solid))),
validator: (description) => description != null && description.isEmpty
? "I'm here to listen. Don't hesitate to open up when you're ready"
: null,
onChanged: widget.onChangedDescription,
);
}

The following should make the TextFormField fill the screen and also make the number of lines unlimited.
Expanded(
child: TextFormField(
maxLines: null,
keyboardType: TextInputType.multiline,
expands: true,
),
)

You can put your TextFormField inside an Expanded widget, which will stretch it over the remaining screen space.
// expanded should be used inside rows or columns
return Column(
children: [
DateMarker(...),
HowDidIFailField(...),
// the expanded stretches the view over the remaining space
Expanded(
child: TextFormField(),
),
]
);
A thing to note is that when the keyboard appears, less space is available and the widget will shrink further. Make sure to test with that as well.

Related

Understanding the Jank happening AlertDialog with TextField and DropdownButton

I have AlertDilaog with TextField and DropDownButton.
Problem:
As soon as, I launch the dialog and clicks on textfield, the alertdialog shifts up and label animation in textfield happens. But while happening this I see jank.
And I did profiling and I am still trying to understand the why it is happening.
Here is the screenshot
And here is the profiling file: https://filebin.net/7wulbm9j88m6jjt3
Can anyone help me in understanding what is this VsyncProcessCallback and whatever happening in selected section(brackets)?
I am just trying to find the root cause of the Jank and remove it.
Thank you in advance.
Code of TextField:
Widget _addProtocolTextField(BuildContext context) {
return Container(
height: 7.h,
width: 70.w,
child: TextField(
controller: _protocolNameController,
style: TextStyle(
color: Theme.of(context).textColor,
fontSize: 13.sp,
),
textAlign: TextAlign.left,
maxLines: 1,
decoration: InputDecoration(
labelText: Strings.protocol_name_lable,
labelStyle: TextStyle(color: ColorConstants.primaryColor),
enabledBorder: _getBorder(),
disabledBorder: _getBorder(),
focusedBorder: _getBorder(),
border: _getBorder(),
),
),
);
}
OutlineInputBorder _getBorder() {
return OutlineInputBorder(
borderSide: BorderSide(color: ColorConstants.primaryColor),
);
}
Since this much code is not enough to provide the real solution, you can refer to the following tips:
Don't make Widget with Function, Prefer to make a separate stateless or stateful widget as per your requirement
You can try this on release build to see if it helps: https://flutter.dev/docs/perf/rendering/shader

WillPopScope does not work from another widget

I have multiple widgets in my flutter app. If I click at another widget, onWillPopScope method which is defined at the top of Widget build(BuildContext context) does not working. Could you give me advice how to fix it? Thanks
See below code:
ExpansionTile(
initiallyExpanded: false,
title:
Text('Solution', style: basicAlertBlack),
children: <Widget>[
Container(
color: Colors.amber.shade50,
height:
MediaQuery
.of(context)
.size
.height /
7,
child: _solutionTextField(),
)
],
),
Code of second widget:
Widget _solutionTextField() {
return TextField(
focusNode: myFocusNode,
keyboardType: TextInputType.multiline,
maxLines: null,
style: solution,
controller: solutionController,
decoration: new InputDecoration(
contentPadding: EdgeInsets.all(8),
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
hintText: 'Enter a solution'));
}
Can you provide more context, please?
As documentations says:
WillPopScope class
Registers a callback to veto attempts by the user to dismiss the enclosing ModalRoute.
It means that it will be called on pop actions. It could be called from android navigation by clicking the return arrow or iOS by swiping from edge left side to right. And every other pop method that you call via Navigator. So it doesn't have a connection with clicking at Widget.

how can a method return 2 widgets which I would later use in a column

I am trying to create a method that returns a text and a TextInput, instead of using a container I want the widgets to be wrapped easily and sent back, I thought it could be achieved by wrapping the two widgets in ():
Widget customTextFormField(String hintText) {
return(
Align(
alignment: Alignment.centerLeft,
child: Text(
"Password",
style: TextStyle(
fontSize: 16.0
),
),
),
TextFormField(
style: TextStyle(color: Colors.grey),
controller: TextEditingController(text: ""),
autofocus: true,
cursorColor: Colors.blue,
decoration: new InputDecoration(
hintStyle: TextStyle(color: Colors.grey),
contentPadding: EdgeInsets.only(left: 15),
border: new OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.grey, width: 1.0),
borderRadius: BorderRadius.circular(4.0),
),
),
));
}
I want this to be used in a Column widget. Using the above code doesn't work as () doesn't wrap the two widgets as one. I also used
Return a list of Widgets.
List<Widget> customTextFormField() {
return [
Container(),
TextFormField(),
];
}
Use spread operator inside the column
return Column(children: [
...customTextFormField()
]);
You either want them to return in a Column
return Column(children: [
Align(),
TextFormField()
];
or return a List, to be used in a column or listview for example
List<Widget> customTextFormField(String hintText) {
return [
Align(),
TextFormField(),
];
}
Edit: Returning widgets from methods is considered an anti-pattern. Check this out for more info (watch the video "Widgets vs helper methods"): https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html
When trying to create a reusable piece of UI, prefer using a widget
rather than a helper method. For example, if there was a function used
to build a widget, a State.setState call would require Flutter to
entirely rebuild the returned wrapping widget. If a Widget was used
instead, Flutter would be able to efficiently re-render only those
parts that really need to be updated. Even better, if the created
widget is const, Flutter would short-circuit most of the rebuild work.

How to create a custom height TextFormField in flutter?

I have a form where there are two TextFormField and one bottom button to validate it but the problem is that the screen is looking awkward. I want the **TextFormField ** the bottom one two cove the area between them completely even if there is no content and become scrollable once it reaches the bottom.
the left one is what I have, but I want the right one, I tried to wrap it with Expandable or Container but it didn't work because I was using border property.
You can achieve this by wrapping the TexFormField widget with an Expanded widget and setting the expands and maxLines property of the TextFormField to true and null respectively.
The TextFormField with take all the available space irrespective of the screen size, check the code provided below for an example:
// wrap it with an Expanded widget
Expanded(
child: TextFormField(
// set the keyboard type to multiline f
keyboardType: TextInputType.multiline,
// set maxlines to null
maxLines: null,
// set expands to true
expands: true,
decoration: InputDecoration(
isDense: true,
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black)
)
),
),
),
You just have to increase the maxLines inside the TextFormField to increase it's size like this:
Container(
height: MediaQuery.of(context).size.height*0.5,//set the size according to your choice
decoration: BoxDecoration(
//Customize your container
color: Colors.red,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
child: TextFormField(
maxLines: 30,//add any number of lines
//Customize your text field
)
),

Flutter textfield expand as user types

I have a textfield and need to have multi-line as below so that the text wraps, however it takes up the space of all the lines that is defined in maxLines. I want to be able to have it look like 1 line and expand as the text wraps. Any ideas of how to do this is flutter?
new TextField(
decoration: const InputDecoration(
hintText: 'Reply',
labelText: 'Reply:',
),
autofocus: false,
focusNode: _focusnode,
maxLines: 1,
controller: _newreplycontroller,
keyboardType: TextInputType.text,
),
Set maxLines to null and it will auto grow vertically.
It's documented (but not entirely clearly) here (edit: I've created a PR to update this, which I should've done to begin with for this question ;). To figure it out I ended up looking at the code for TextField and its superclass(es), seeing what the behavior would be if set to null.
So your code should be as follows:
new TextField(
decoration: const InputDecoration(
hintText: 'Reply',
labelText: 'Reply:',
),
autofocus: false,
focusNode: _focusnode,
maxLines: null,
controller: _newreplycontroller,
keyboardType: TextInputType.text,
),
If you're trying to make it autogrow horizontally, you probably shouldn't - at least not based on the text content. But I'm asuming you want to make it autogrow vertically.
Using this should do the trick:
keyboardType: TextInputType.multiline,
minLines: 1,
maxLines: 20,
maxLength: 1000,
Adding the minLines and MaxLines is important in order to get the required behaviour, whereas maxLength is a treat!
Maybe too late, but better late than never!
As shown in the first answer, setting maxLines to null will do the trick. However this would allow the textfield to grow infinitely.
To have more control, set minLines to 1 and maxLines as needed.
Hope this helps!
Code Sample:
TextField(minLines:1,maxLines:8)
The accepted answer works great for growing vertically. If you'd like the TextField to start small and expand horizontally as the user types, you can do the following:
IntrinsicWidth(
child: TextField(...
),
In my case I wanted it centered on the screen (horizontally), so I did:
Center(
child: IntrinsicWidth(
child: TextField()
)
)
Setting to null was working the same as setting to 1 (it grows horizontally just one line).
I think you have to set minLines and maxLines.
I'm using minLines: 1 and maxLines: 2 and when the first line reaches the end it expands another line. When the second line reaches the end it scroll the second to the first and creates the third line. So you will have to set maxLenght too.
If you want to set a predefined height, use expands: true:
SizedBox(
height: 200,
child: TextField(
decoration: InputDecoration(hintText: 'Enter a message'),
maxLines: null,
expands: true,
),
)
You can simply use this;
TextField get _text => TextField(
maxLines: null,
decoration: InputDecoration(
constraints: BoxConstraints(
maxHeight: responsiveHeight,
maxWidth: responsiveWidth),
contentPadding: EdgeInsets.symmetric(
horizontal: responsiveHorizontalPadding,
vertical: responsiveVerticalPadding),
disabledBorder: InputBorder.none,
border: InputBorder.none,
enabledBorder: InputBorder.none,
isDense: false,
));
#Rabi Roshan,
As shown in the first answer, setting maxLines to null will do the
trick. However this would allow the textfield to grow infinitely.
To have more control, set minLines to 1 and maxLines as needed. Hope
this helps!
Thank you so much!
I also prefer this version much more because it will only expand if the user inputs more than one line. And if it exceeds the maxLines, it will scroll vertically which is what should normally happen and what all big Chat Apps use.
textfield and need to have multi-line as below so that the text wraps, however it takes up the space of all the lines that is defined in maxLines. I want to be able to have it look like 1 line and expand as the text wraps
Container(
child: new TextField (
keyboardType: TextInputType.multiline,
minLines: 1,
maxLines: 10,
decoration: new InputDecoration(
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(10.0),
),
),
filled: true,
hintStyle: new TextStyle(color: Colors.grey[800]),
hintText: "Type in your text",
fillColor: Colors.white70),
),
padding: new EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 16.0),
);