So I was coding the search bar and I used the TextFormField widget but I have a problem with this. I have two screens and the widget is in both screens. On the first screen when you tap the TextFormField it reroutes you to the second screen and there I have set autofocus to true. The only problem is that once you done searching for accounts and try to route back to the previous screen the TextFormField autofocuses again and I do not want it like that.
And here's my code.
\\\ appbar
title: Padding (
padding: const EdgeInsets.only(left: 5.0, right: 5.0),
child: TextFormField(
autofocus: false,
cursorColor: Colors.purple,
onTap: () {
FocusScope.of(context).unfocus();
TextEditingController().clear();
Get.to(() => const SearchPage());
},
decoration: InputDecoration(
suffixIcon: const Icon(
MdiIcons.databaseSearch,
),
labelText: 'Go Wild',
labelStyle: GoogleFonts.parisienne(
fontSize: 21.0,
),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.purple),
borderRadius: BorderRadius.circular(34.0),
),
),
),
),
),
/// body of the Scaffold
I have tried different answers but none of them helps. Please help me
Related
I am new-ish to flutter and I have come across a problem and I would really appreciate your help.
I have two separate forms on two different screens. Clicking the "Next" button on the first page validates the form and pushes to the second page using Navigator.push(). And all works fine until I come back to the first page using the arrow on the top left corner in the app bar which is automatically created. The data inside the TextFormFields on the first page is still filled out which is good but when I click next (which validates and pushes to the second page using Navigator.push) and go to the second page all the data inside the TextFormFields has disappeared.
My intention is to have the user data entered in the TextFormFields of both forms persistent after Navigating back and forth through different screens.
I have already looked at this stackoverflow page but the solution there did not fix my issue.
I looked into shared_preferences but the people on the Flutter discord suggested not to use it.
Here is the code:
First Page
Second Page
(I used PasteUbuntu for the code as it was a bit too long so I didn't want to copy it in this post)
This is the definition for my formField() function:
class formField extends StatelessWidget {
Function validator;
Function onSaved;
String fieldTitle;
String hintText;
TextEditingController textController;
TextInputType keyboardStyle;
formField(
{this.onSaved,
this.validator,
this.fieldTitle,
this.hintText,
this.textController,
this.keyboardStyle});
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RichText(
textAlign: TextAlign.left,
text: TextSpan(
text: fieldTitle,
style: GoogleFonts.questrial(
fontSize: 16,
color: Colors.black,
fontWeight: FontWeight.w500,
)),
),
SizedBox(height: 10),
Container(
width: 335,
height: 50,
child: Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(10.0),
child: TextFormField(
validator: validator,
onSaved: onSaved,
textAlignVertical: TextAlignVertical.bottom,
textCapitalization: TextCapitalization.sentences,
keyboardType: keyboardStyle,
controller: textController,
decoration: InputDecoration(
filled: true,
fillColor: Color(0xFFF0F0F0),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFFE8E8E8))),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xFFE8E8E8)),
borderRadius: BorderRadius.circular(8.0),
),
hintText: hintText,
hintStyle:
GoogleFonts.inter(color: Color(0xFFBDBDBD), fontSize: 16),
),
style: GoogleFonts.inter(color: Colors.black, fontSize: 16),
),
),
),
],
);
}
}
I want to add a animation in a search bar when the user taps on it (just like the animation in whatsApp or telegram [only in iOS])
here is the animation
I used Hero widget to do so but the widget is not working, I don't know why. Here is my code for it
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
//some widgets above the search bar
Hero(
tag: 'search',
child: Container(
height: 38,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(32),
),
child: TextField(
cursorColor: Colors.blue,
decoration: InputDecoration(
hintStyle: TextStyle(fontSize: 16),
hintText: "Search here",
prefixIcon: Icon(Icons.search),
border: InputBorder.none,
),
),
),
),
//some more widgets here inside the column
])
This is part of code for 1st page and the other page is just the search bar.
This is the other page which is almost the same
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Hero(
tag: 'search',
child: Container(
height: 38,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(32),
),
child: TextField(
cursorColor: Colors.blue,
decoration: InputDecoration(
hintStyle: TextStyle(fontSize: 16),
hintText: "Search here",
prefixIcon: Icon(Icons.search),
border: InputBorder.none,
),
),
),
),
),
);
}
Also is there any other way to do it?
EDIT: It's now working fine with Hero widget but it does not show that exact behaviour as in the above gif. How should I do that, if someone has any other method to achieve that, can also answer.
Hero is used when moving between different pages here(in the above animation) we are not navigating to any other page, so, remove the Hero widget
This can be done with Transform.translate in combination with Opacity() widget in Flutter.
Wrap the respective widget with Transform.translate create a Tween Animation and change its height with the help of Offset(dx, dy) (in this case dx will be 0 and dy will be the changing height), negative dy value will move the widget upwards. Also wrap it with Opacity() and change the value with the changing value of height.
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Transform.translate(
offset: Offset(0, animatedHeightFromTweenAnimation)
child: Opacity(
opacity: animatedHeightFromTweenAnimation/maxHeightValue;
child: anyWidget()
)
)
Container(
height: 38,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(32),
),
child: TextField(
cursorColor: Colors.blue,
decoration: InputDecoration(
hintStyle: TextStyle(fontSize: 16),
hintText: "Search here",
prefixIcon: Icon(Icons.search),
border: InputBorder.none,
),
),
),//container
RaisedButton(
onPressed: () => controller.forward(), //here controller is animation controller
//the above line will start the animation
child: Text("press it"),
),
//some more widgets here inside the column
])
This has been very confusing to me since the TextField wrapped in a SizedBox only, works perfectly; but it appears to be a simple image (it can't be tapped, nor focused) when I wrap that same piece of code in a Transform.translate widget.
Also, if I change the Transform.translate to a Positioned widget, the TextField works perfectly, but I'd like to understand why this is happening, because I am required to use Transform.translate over Positioned for this special project.
class Login extends StatelessWidget {
Login({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xfff4f6fa),
body: Stack(
children: <Widget>[
SizedBox(
width: 302.0,
height: 60.0,
child: TextField(
decoration: InputDecoration(
hintText: 'Correo electrónico *',
prefixIcon: Icon(Icons.send),
border: OutlineInputBorder(
borderSide:
BorderSide(width: 1.0, color: const Color(0xffe7e7e7)),
borderRadius: BorderRadius.circular(4.0),
),
),
style: TextStyle(
fontFamily: 'Nunito',
fontSize: 14,
color: const Color(0xff777777),
height: 1.4285714285714286,
),
textAlign: TextAlign.left,
onChanged: (String value) async {
},
onSubmitted: (String value) async {
},
),
),
// Positioned(
Transform.translate(
offset: Offset(36.0, 317.8),
// left: 36,
// top: 317.8,
child:
// Adobe XD layer: 'input:mail' (component)
SizedBox(
width: 302.0,
height: 60.0,
child: TextField(
decoration: InputDecoration(
hintText: 'Correo electrónico *',
prefixIcon: Icon(Icons.send),
border: OutlineInputBorder(
borderSide:
BorderSide(width: 1.0, color: const Color(0xffe7e7e7)),
borderRadius: BorderRadius.circular(4.0),
),
),
style: TextStyle(
fontFamily: 'Nunito',
fontSize: 14,
color: const Color(0xff777777),
height: 1.4285714285714286,
),
textAlign: TextAlign.left,
onChanged: (String value) async {
},
onSubmitted: (String value) async {
},
),
),
),
],
),
);
}
}
As mentioned before, both inputs show on the screen (one at the center and one at the top) only the TextField wrapped with a SizeBox (first element of the Stack, at the top of the sreen)can be tapped, nothing happens when the one at the center of the screen (second element of the stack, located there because of the translation) is tapped.
Try debugging and see the layout grid lines and correct boundaries of widget using Flutter inspector.
That should give you a better idea at why is it behaving this way.
Seems like when You use the Transform widget, it doesnt register the hit as it merely moves the boundaries and not the tap area.
Try wrapping the Transform widget with a GestureDetector and see.
You can also follow a similar issue on GitHub:
https://github.com/flutter/flutter/issues/27587
I am setting a text field which will expands when Enter is pressed in the keyboard
when i tried to set null in max lines it does not show the text inside text field
i even set that expands = true
i used media query size in somewhere which is size.height in the code
i wrapped the text field within the Flexible widget
and add some padding then the total flexible widget is wrapped within a Row
and finally the row is wrapped within a Container
so this code is not working help me to fix this
Container(
height: size.height * .059,
width: double.infinity,
child: new Row(
children: <Widget>[
new Flexible(
child: Padding(
padding: EdgeInsets.only(right: size.width * 0.007),
child: new TextField(
controller: _textFieldController,
textInputAction: TextInputAction.newline,
keyboardType: TextInputType.multiline,
maxLines: null,
expands: true,
style: TextStyle(color: Colors.black),
cursorColor: Colors.blue,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: BorderSide(color: Color(0xff8e9291))),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: BorderSide(color: Color(0xff8e9291))),
prefixIcon: Icon(
Icons.message,
color: Color(0xff8e9291),
),
hintText: "Type a message",
hintStyle: TextStyle(
color: Color(0xff8e9291),
),
),
),
),
),
FloatingActionButton(
backgroundColor: Colors.blue[400],
onPressed: () {
},
tooltip: 'Send',
child: RotationTransition(
turns: AlwaysStoppedAnimation(-35 / 360),
child: Icon(
Icons.send,
size: 20,
)),
),
],
),
),
this is the Text field i'm using..
You could remove the height of the Container since that will make a fixed height, and remove the expands of the TextField since that is to make it to fill its parent height.
You could set MaxLine property to null 'maxLines: null`
this will enable textField to Expand Vertical
I need to bottom center a button that is contained within a ListView. By bottom, I mean at the bottom of the screen, or if the screen content is longer than the height of the screen, at the end of the content.
I can do this using a Column with a Spacer widget because the height is defined, however my screen has text input on it. If I use a Column instead of a ListView, the screen overflows when I'm typing.
How can I either
Bottom center a button, or
Use a Column but prevent the screen from resizing or overflowing when typing; I'd like it to ether be scrollable, or simply have the keyboard cover the screen content while typing.
Basic code example:
return Scaffold(
body: Center(
child: Container(
width: workingWidth,
child: Center(
child: ListView(children: <Widget>[
ScreenHeader("Tell Us a Little About Yourself"),
TextFormField(
maxLines: 16,
controller: bioController,
autocorrect: true,
textCapitalization: TextCapitalization.sentences,
maxLength: 500,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(paddingH5),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: colorPrimary)),
border: UnderlineInputBorder(
borderSide: BorderSide(color: colorMuted)),
hintText: "Enter your bio here...",
hintStyle: textMuted,
),
),
Spacer(), //This doesn't work because I am using a ListView instead of a Column
RoundedButton(
buttonText: 'Continue',
buttonStyle: buttonPrimary,
onPressed: () {}
),
],)
),
),
),
);
To use a Column without yellow/black stripes error when opening the keyboard, you need to wrap it into a SingleChildScrollView, but Spacer will not work in that case if you do not declare the height of its RenderFlex parent.
You can use MediaQuery.of(context).size.height to get the screen size on its context and set to your Container.
At the end you can achieve the desired layout with this:
return Scaffold(
body: SingleChildScrollView(
child: Container(
width: workingWidth,
height: MediaQuery.of(context).size.height,
child: Column(
children: <Widget>[
ScreenHeader("Tell Us a Little About Yourself"),
TextFormField(
maxLines: 16,
controller: bioController,
autocorrect: true,
textCapitalization: TextCapitalization.sentences,
maxLength: 500,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(paddingH5),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: colorPrimary)),
border: UnderlineInputBorder(
borderSide: BorderSide(color: colorMuted)),
hintText: "Enter your bio here...",
hintStyle: textMuted,
),
),
Spacer(),
RoundedButton(
buttonText: 'Continue',
buttonStyle: buttonPrimary,
onPressed: () {}
),
],
),
),
),
);