Exiting Focus from Multiline - Flutter - flutter

I am currently trying to make a page that take notes on my app so I am using the multiline keyboard type to keep track of the text. However, I am having difficulties escaping the focus of the text. Return brings a new line (which I want it to do) but I am unsure as to when I have onSubmit or onEditingComplete because I never actually submit anything using multiline. In addition, tapping outside of the textfield does not exit the focus of the field. Here is the code that I wrote please let me know if you have any recommendations!
import 'package:flutter/material.dart';
class NoteDetail extends StatefulWidget {
#override
_NoteDetailState createState() => _NoteDetailState();
}
class _NoteDetailState extends State<NoteDetail> {
#override
Widget build(BuildContext context) {
final dimensions = MediaQuery.of(context).size;
return LimitedBox(
maxHeight: dimensions.height - 100,
maxWidth: dimensions.width - 100,
child: Column(
children: <Widget>[
SizedBox(
height: dimensions.height * 0.10,
),
TextField(
keyboardType: TextInputType.multiline,
//this allows the text to work with multiple lines
maxLines: null,
//no max lines making it scroll forever
decoration: InputDecoration(
hintText: 'Start taking some notes',
//shows text before the user starts to text
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
//this removes the border all together
contentPadding:
EdgeInsets.symmetric(horizontal: dimensions.width * 0.1),
//giving the content some padding on the side
),
),
],
),
);
}
}

Related

How to implement search page via TextField in Flutter?

I need to make a search page. Made by means of TextField a field on clicking on which the page of search should open. Tell me how to implement clicking on the TextField and so that the back button appears on the left and the buttons disappear on the right?
code
TextFormField(
style: constants.Styles.textFieldTextStyleWhite,
cursorColor: Colors.white,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(
top: 15, // HERE THE IMPORTANT PART
),
border: InputBorder.none,
prefixIcon: Align(
alignment: Alignment.centerLeft,
child: SvgPicture.asset(
constants.Assets.search,
width: 20,
height: 20,
))),
)
Normal state
After clicking on the line
Wrap everything into a StatefulWidget.
Then, when clicking the TextFormField, change the attributes of the StatefulWidget.
class YourPage extends StatefulWidget {
_YourPageState createState() => _YourPageState();
}
class _YourPageState extends State<YourPage> {
var myBool = false;
// Initialize your Row-buttons here
// ...
void changeRow(){
setState(() {
// Hide or show Row-buttons here.
myBool = true;
});
}
#override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
body: Row(children:[
myBool == true
? Icon( ...) // shows icon
: SizedBox.shrink(), // shows nothing
TextFormField( onTap: () => changeRow() ),
// other BUTTONs here
])
),
);
}
}
There are a few possibilities for an AppBar to show Text or Buttons.
Check these examples:
https://www.fluttercampus.com/tutorial/10/flutter-appbar/

New Textfield created appear with previous textfield's value in flutter

I have this Widget to register. Inside I want to ask for 6 inputs to register, but as not too much space on the screen, I splitted in 2 pair of 3. I show three at first in a form and when the user press the continue button I show the other 3. However, when I press the continue button, the new 3 pair of TextField appear with the same value of the previous ones. And they move position a little under. I don't know why it happens since each of those 6 fields is different Widget function.
I created two variables form1 and form2 to hold the different forms
#override
void initState() {
super.initState();
form1 = <Widget>[
firstForm(),
Text("Or Sign Up with social media"),
SizedBox(
height: 20,
),
socialMediaButtons(),
SizedBox(
height: 50,
),
Text("Have an account? Login")
];
form2 = <Widget>[
secondForm(),
Text("Or Sign Up with social media"),
SizedBox(
height: 20,
),
socialMediaButtons(),
SizedBox(
height: 50,
),
Text("Have an account? Login")
];
}
All the text field have the same format as the text field below, I only changed the variable for their respecting field.
Widget firstNameField() {
return TextFormField(
initialValue: "",
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: 10, left: 20, right: 20),
border: InputBorder.none,
hintText: "First Name",
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)),
onChanged: (val) {
setState(() => firstName = val);
},
);
}
I combined the text fields in two widgets (firstForm and secondForm). (Shown firstForm but it is the same format as second, just called the functions for the other widgets).
Widget firstForm() {
return Column(
children: <Widget>[
emailPassField(),
SizedBox(
height: 50,
),
continueButton(),
SizedBox(
height: 50,
),
],
);
}
Then this is the continue button widget which when pressed. show the second form. I change the step variable to 2 to go to the second form.
Widget continueButton() {
return ButtonTheme(
minWidth: 185.0,
height: 48.0,
child: RaisedButton(
color: Colors.black,
textColor: Colors.white,
child: Text("continue"),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(50.0)),
onPressed: () => setState(() => step = 2),
));
}
When the variable step is changed, I created this function (getForm) to be called and to show the correct form array variable for the children of the column.
#override
Widget build(BuildContext context) {
return Material(
child: Expanded(
child: Stack(
children: <Widget>[
// banner with picture
Positioned(
child: banner(),
),
// Login Elements Container
Positioned(
child: Container(
margin: EdgeInsets.only(top: 300.0),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 5,
blurRadius: 20,
offset: Offset(0, 0))
],
borderRadius: BorderRadius.only(
topRight: Radius.circular(50),
topLeft: Radius.circular(50))),
child: Center(
child: Column(
children: getForm(step),
),
),
),
)
],
),
),
);
}
//functions for switching forms
getForm(int form) {
if (form == 1) {
return form1;
} else if (form == 2) {
return form2;
}
}
This is how the first step of the form appear.
first form
If I don't enter any data in the text fields and press the continue button, the second form with the correct text fields will appear as shown in this below image. You can see that they have the correct hint text.
second form
However if I enter some data on the first step of the form (seen in second form with data step 1), and then press the continue button, in the second step, the text fields will move down a little bit and the same value entered in the previous text fields will appear in the others too(second form with data step 2). can someone help me please, I don't what's going on there? I hope you understand the code and be able to help me please.
second form with data step 1
second form with data step 2
You need to create a TextEditingController for each TextFormField.
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
...
final _cityController = TextEditingController();
...
// initState
...
// dispose of all TextEditingControllers
#override
void dispose {
_emailController.dispose();
...
_cityController.dispose();
super.dispose();
}
// do this for every TextFormField
Widget firstNameField() {
return TextFormField(
// pass the corresponding controller, no need to set initial value if empty
controller: _firstNameController,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: 10, left: 20, right: 20),
border: InputBorder.none,
hintText: "First Name",
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)),
onChanged: (val) {
setState(() => firstName = val);
},
);
}
Use a unique TextEditingcontroller for each textfield...by this way the values won't overlap each others textfield value.

Flutter enabled and focus textformfield

I create a profile page and i have 4 textformfield. I want to on tap icon activate textformfield and focus at the same time. Now I need tap twice on icon and first activated field, secondly focused.
How to solve it?
My code:
class UserProfile extends StatefulWidget {
#override
_UserProfileState createState() => _UserProfileState();
}
class _UserProfileState extends State<UserProfile> {
FocusNode myFocusNode;
bool isEnable = false;
#override
void initState() {
super.initState();
myFocusNode = FocusNode();
}
#override
void dispose() {
myFocusNode.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.fromLTRB(40.0, 50.0, 20.0, 0.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Flexible(
child: TextFormField(
enabled: isEnable,
focusNode: myFocusNode,
),
),
IconButton(
icon: Icon(Icons.edit),
onPressed: () {
setState(() {
isEnable = true;
FocusScope.of(context).requestFocus(myFocusNode);
});
})
],
),
You should use autofocus: isEnable instead.
just do like below in your ontap
setState(() {
if(isEnable)
Future.delayed(const Duration(milliseconds: 10), ()
{FocusScope.of(context).requestFocus(myFocusNode);
});
isEnable = true;
});
in first time isEnable is false so focusing not call and just enabling work and in other times get focus too.
you can't focus widget until disabled and when you enabling widget. when you do focusing and enabling at same time in ui tread it's try focusing before enabling because of their rendering time.if you post some delay to focusing the problem get solving.
Try using readOnly instead of enabled in TextFormField
I faced similar issue when I had multiple TextFields to enable kinda PIN input. And some of that had to be dynamically enabled and disabled plus prevent users from entering value in the next field while they haven't finished the previous one. I've tried a lot of approaches and focusing field after some delay was not a way to go because I wanted the keyboard to always be available while entering. So I've took a crazy path and solved this next way:
onTap: () => _focusNodes[_currentLetterIndex].requestFocus()
where _focusNodes are for each letter and _currentLetterIndex is calculated programmatically during input (when finished letter 0 -> current becomes 1 and so on). As the result when user tried to tap on next field - it was automatically refocused to the current one which behaves like the next field is disabled.
An example of the full text field looks like this (don't pay attention to decorations etc.)
TextField(
key: ValueKey(index),
controller: _editingControllers[index],
onTap: () => _focusNodes[_currentLetterIndex].requestFocus(),
focusNode: _focusNodes[index],
textAlign: TextAlign.center,
showCursor: false,
maxLength: 2,
enableInteractiveSelection: false,
autocorrect: false,
enableSuggestions: false,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
height: 1.2,
decoration: TextDecoration.none),
decoration: InputDecoration(
fillColor: !_wordCompleted &&
!correct &&
_editingControllers[index].text.isNotEmpty
? const Color(0xFFFFEEF0)
: Colors.white,
filled: !correct,
counterText: "",
border: defaultInputBorder,
focusedBorder: !correct &&
!_wordCompleted &&
_editingControllers[index].text.isNotEmpty
? incorrectInputBorder
: focusedInputBorder,
enabledBorder: _wordCompleted
? focusedInputBorder
: correct
? correctInputBorder
: defaultInputBorder,
errorBorder: defaultInputBorder,
disabledBorder: _wordCompleted
? focusedInputBorder
: correct
? correctInputBorder
: defaultInputBorder,
contentPadding: const EdgeInsets.only(left: 2)),
),

How is it possible to edit Text in a flutter application?

I want to show a paragraph and once the user selects a part of it, somehow he can get the option to edit the selected text and the string will change and replace the old text, please tell me if that's possible.
I have found flutter_selectext plugin but it doesn't show in the examples if it's possible to edit the text or the string that provides the text to the widget it just shows that it can copy which I cannot use.
I believe you want to have a functionality of EditText just like in android. I have a similar problem before. Here is how Solve it. Define the TextEditingController in State.
and you can initialize in the InitState. you can use listener for more controll of text ( like saving the previous old text)
class _ProfileEditPageState extends State<ProfileEditPage> {
TextEditingController nameController;
.. }
#override
void initState() {
nameController = TextEditingController();
super.initState();
}
Here is how you can implement in your widget.
Padding(
padding: const EdgeInsets.only(right: 50),
child: TextField(
autofocus: false,
decoration: InputDecoration(
disabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(5.0)),
borderSide: BorderSide(color: Colors.transparent)),
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(5.0)),
borderSide: BorderSide(color: Colors.blue)),
border: InputBorder.none,
),
controller: nameController
..text = _userProfileData.background, //this is your text
),
),

Text in the TextField disappears when keyboard is removed

Text entered in my TextField widget disappears when I remove the keyboard from the view.
There are two TextField's, title and description. The above problem only occurs for the title but not with the description.
Here's the relevant excerpt from the build method:
#override
Widget build(BuildContext context) {
_note = widget._note; // This is coming from StatefulWidget Class above
TextStyle textStyle = Theme.of(context).textTheme.title;
_titleController.text = _note.title;
_descriptionController.text = _note.description;
return Scaffold(
body: ListView(
children: <Widget>[
Padding(
padding: EdgeInsets.all(15.0),
child: TextField(
style: textStyle,
controller: _titleController,
decoration: InputDecoration(
labelText: "Title",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
),
),
Padding(
padding: EdgeInsets.all(15.0),
child: TextField(
style: textStyle,
controller: _descriptionController,
decoration: InputDecoration(
labelText: "Description",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
),
),
...
}
}
Screenshots of Keyboard shown & removed.
This occurs because you are setting the text in your build method. This build method can get invoked at any time, e.g. when the keyboard is contracted because the UI needs to react to that.
This means that you should move this code to initState:
#override
void initState() {
_note = widget._note;
_titleController.text = _note.title;
_descriptionController.text = _note.description;
super.initState();
}
initState is only called once when the your widget is inserted into the build tree.
I am not sure why this only happens with one of the TextFields's. I assume that you are using the TextController's somewhere else to set the Note's content, which could cause this behavior.
Furthermore, you should probably avoid using a leading underscore _ for _note in your StatefulWidget (widget._note) as you access it from your State.