How to remove Space at the bottom of TextField in flutter? - android

I can't figure out why there is space at the bottom of TextField between the text and the blue line.
Here is my code :
Future<Null> _selectNoteType (BuildContext context) async {
switch (await showDialog<Null>(
context: context,
builder: (BuildContext context) {
return new SimpleDialog(
title: const Text('Select Note Type'),
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: new TextField(
keyboardType: TextInputType.text,
maxLines: 1,
style: new TextStyle(
color: Colors.black,
fontSize: 20.0
),
),
),
new SimpleDialogOption(
onPressed: () {},
child: const Text('Text')
),
new SimpleDialogOption(
onPressed: () {},
child: const Text('Checklist')
),
],
);
}
)) {}
}

In my case the TextField would still not collapse even after using InputDecoration.collapsed().
My version doesn't have any padding at all and takes the minimum size:
TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(0.0),
isDense: true,
border: InputBorder.none,
),
minLines: 1,
maxLines: 1,
);
Live preview:
https://dartpad.dev/3f9149a1c8f5eec352c796e7585e233c

You can use a collapsed InputDecoration for the decoration: property of the TextField.
Future<Null> _selectNoteType(BuildContext context) async {
InputDecoration decoration = const InputDecoration.collapsed()
..applyDefaults(Theme.of(context).inputDecorationTheme);
switch (await showDialog<Null>(
context: context,
builder: (BuildContext context) {
return new SimpleDialog(
title: const Text('Select Note Type'),
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: new TextField(
decoration: decoration,
keyboardType: TextInputType.text,
maxLines: 1,
style: new TextStyle(color: Colors.black, fontSize: 20.0),
),
),
new SimpleDialogOption(
onPressed: () {}, child: const Text('Text')),
new SimpleDialogOption(
onPressed: () {}, child: const Text('Checklist')),
],
);
})) {
}
}
But you must know the consequences of using a collapsed InputDecoration. From the documentation:
/// Whether the decoration is the same size as the input field.
///
/// A collapsed decoration cannot have [labelText], [errorText], an [icon].
///
/// To create a collapsed input decoration, use [InputDecoration..collapsed].
final bool isCollapsed;
And for the InputDecoration.collapse() constructor:
/// Defines an [InputDecorator] that is the same size as the input field.
///
/// This type of input decoration does not include a border by default.
///
/// Sets the [isCollapsed] property to true.
const InputDecoration.collapsed({

isDense will do the trick. uses less vertical space
TextField(
decoration: InputDecoration(
isDense: true,
),
);

Related

Why is nothing displayed in my flutter widget?

return 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("Se connecter"),
backgroundColor: Colors.red,
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child:
Container(
margin: EdgeInsets.all(24),
decoration: BoxDecoration(color: Colors.white),
child :
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
width: 160.0,
color: Colors.red,
),
Container(
width: 160.0,
color: Colors.blue,
),
]
),
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email',
hintText: 'Enter email',
contentPadding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
),
),
TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
hintText: 'Enter Password',
contentPadding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
),
),
Text(
'10',
style: Theme.of(context).textTheme.headlineMedium,
),
// ↓ Add this.
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.red,
),
onPressed: () async {
print('button pressed!');
Map<String,String?> infos = {
'app_id' : dotenv.env['app_id'],
'database' : dotenv.env['database'],
'mail' : dotenv.env['mail'],
'pass' : dotenv.env['pass'],
//'debug-mr' : dotenv.env['debug-mr'],
};
var a = await HttpGet('/auth', infos);
Map<String, dynamic> map = jsonDecode(a.body);
print(map['auth_mode']);
},
child: Text('Next'),
),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: null,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
I want first to create a column in 2 columns in the first row of the view, then display in differents rows differents components after the second row... each one one row
..but there is not that
I expect that it appears anything of my screen view, or nothing is displayed, all is white
Thanks in advance if you are able to help me
Please add shrinkWrap = true inside ListView,
Or Wrap Expand widget outside ListView,
If scrollDirection = axis.horizontal, Please Wrap LisView in SizeBox and set Height for SizeBox
Because of Column [ ListView...] Firstly check Unbounded height / width | Decoding Flutter.
For your case, Container doesn't have any height.
try providing height.
You can wrap the ListView with Expanded widget, it will get available space for ListView.
class _FR43State extends State<FR43> {
#override
Widget build(BuildContext context) {
return 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("Se connecter"),
backgroundColor: Colors.red,
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Container(
margin: EdgeInsets.all(24),
decoration: BoxDecoration(color: Colors.white),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
width: 160.0,
height: 200,
color: Colors.red,
),
Container(
width: 160.0,
height: 200,
color: Colors.blue,
),
]),
),
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email',
hintText: 'Enter email',
contentPadding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
),
),
TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
hintText: 'Enter Password',
contentPadding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
),
),
Text(
'10',
style: Theme.of(context).textTheme.headlineMedium,
),
// ↓ Add this.
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.red,
),
onPressed: () async {
// print('button pressed!');
// Map<String,String?> infos = {
// 'app_id' : dotenv.env['app_id'],
// 'database' : dotenv.env['database'],
// 'mail' : dotenv.env['mail'],
// 'pass' : dotenv.env['pass'],
// //'debug-mr' : dotenv.env['debug-mr'],
// };
// var a = await HttpGet('/auth', infos);
// Map<String, dynamic> map = jsonDecode(a.body);
// print(map['auth_mode']);
},
child: Text('Next'),
),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: null,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

How to disable user to go back to login screen after user login

I have an issue that when the user clicks on the login button it redirects to the home page but when I press back it redirects me to the login page again. this is not the correct flow. after the user login, it can't be able to access the login page thats the flow. but in my code, it doesn't work.
Please see my code to help me how to resolve it.
How do I disable the login screen after login?
Here is the code:-
Future<void> main() async{
Auth.prefs = await SharedPreferences.getInstance();
runApp(
Auth.prefs?.getBool("loggedIn") == true ? CardApp() : Login()
);
}
class Login extends StatefulWidget {
Login({Key? key}) : super(key: key);
#override
_Login createState() => _Login();
}
class _Login extends State<Login>{
var logstatus = Auth.prefs!.getBool('loggedIn');
TextEditingController _user = TextEditingController();
TextEditingController _pass = TextEditingController();
var user = "";
var pass = "";
var statusStep = "";
var Steps = "";
var _UserID = "";
bool _isPass = true;
get import => null;
#override
Widget build(BuildContext context){
final Size size = MediaQuery.of(context).size;
final ThemeData themeData = Theme.of(context);
final double padding = 25;
final sidePadding = EdgeInsets.symmetric(horizontal: padding);
//return SafeArea(
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
//colors: const [Color.fromRGBO(132,105,211,1), Color.fromRGBO(93,181,233,1), Color.fromRGBO(86,129,233,1)],
colors: const [Colors.white, Colors.white]
),
),
width: size.width,
//height: size.height,
child: ListView(
physics: BouncingScrollPhysics(),
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
addVerticalSpace(padding),
Padding(
padding: sidePadding,
child: Column(
children: <Widget>[
addVerticalSpace(20),
Image.asset(
'assets/images/logo.png',
height: 150,
scale: 2.5,
), // Image.asset
], //<Widget>[]
),
),
addVerticalSpace(10),
addVerticalSpace(padding),
Padding(
padding: sidePadding,
child: Text(
'Sign In',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.black,
),
),
),
addVerticalSpace(30),
Padding(
padding: sidePadding,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(child: TextField(
controller: _user,
keyboardType: TextInputType.text,
obscureText: false,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color.fromARGB(153, 154, 154, 154)),
borderRadius: BorderRadius.circular(8.0),
),
hintText: 'Email',
hintStyle: TextStyle(color: Color.fromARGB(
153, 154, 154, 154)),
contentPadding: EdgeInsets.fromLTRB(25,10,25,10),
focusedBorder:OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff9A9A9A99), width: 1.0),
borderRadius: BorderRadius.circular(8.0),
)
),
))
],
),
addVerticalSpace(15),
Row(
children: <Widget>[
Expanded(child: TextField(
controller: _pass,
keyboardType: TextInputType.text,
obscureText: _isPass,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(
_isPass ? Icons.visibility : Icons.visibility_off),
onPressed: () {
setState(() {
_isPass = !_isPass;
});
}),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color.fromARGB(153, 154, 154, 154)),
borderRadius: BorderRadius.circular(8.0),
),
hintText: 'Password',
hintStyle: TextStyle(color: Color.fromARGB(
153, 154, 154, 154)),
contentPadding: EdgeInsets.fromLTRB(25,0,25,0),
fillColor: Colors.white,
focusedBorder:OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xff9A9A9A99), width: 1.0),
borderRadius: BorderRadius.circular(8.0),
)
),
style: TextStyle(
height: 1.0,
),
)
)
],
),
addVerticalSpace(10),
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Forgotpass()),
);
},
child: Text(
"Forgot Your Password?",
style: TextStyle(
color: Colors.black,
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
)
),
addVerticalSpace(20),
Padding(
padding: const EdgeInsets.all(0.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
//primary: Color.fromRGBO(152,165,244,1),
primary: Color(0xffFDA766),
minimumSize: const Size.fromHeight(50),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0),)// NEW
),
child: const Text(
'SIGN IN'
),
onPressed: () async{
user = _user.text;
pass = _pass.text;
final body = null;
final url = Uri.https('www.*******.net', '/index.php',{'act':'login','user': user, 'pass': pass});
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: body
);
int statusCode = response.statusCode;
Map<String, dynamic> responseBody = jsonDecode(response.body);
setState(() {});
var list = responseBody['error'];
var stringList = list.join("\n");
var statusRes = responseBody['status'];
var UserID = responseBody['usr'];
if(statusRes == 'success'){
Auth.prefs?.setBool("loggedIn", true);
Auth.prefs?.setBool("onlinestatus", true);
Auth.prefs?.setString('usrid', UserID);
FCMService().getFCMToken();
Navigator.of(context).pop();
Navigator
.of(context)
.pushReplacement(
MaterialPageRoute(
builder: (BuildContext context) => CardApp()
)
);
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => CardApp()),
// );
} else {
//print('error: '+statusRes);
showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: Text("Login Failed!", style: TextStyle(color: Color(0xff8f9df2), fontWeight: FontWeight.bold),),
content: Text(
'${stringList}',
style: TextStyle(
color: Colors.red,
),
),
actions: <Widget>[
TextButton(
//onPressed: () => Navigator.pop(context, 'OK'),
onPressed: () {
Navigator.pop(context, 'OK');
},
child: const Text('OK'),
),
],
),
);
}
setState(() {});
},
),
),
],
),
),
],
),
],
)
),
);
//);
}
}
Here is my login screen see this code and help me with how can i do this.
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (BuildContext context) => CardApp()));
to this
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => const CardApp()),
(Route<dynamic> route) => false);
route dynamic false will remove all route and user cant go back
you are using
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => CardApp()));
which stack the new screen on the top of the login which on pressing back button is shown again if you want to remove the beneath screen from the stack and disable the back button use this function instread
Navigator.of(context)
.pushAndRemoveUntil(MaterialPageRoute(
builder: (BuildContext context) => CardApp()), (route) => false);

TextField unfocuses when the soft keyboard appears

For some reason, when I press the TextField, it focuses for a split second and then unfocuses immediately as the soft keyboard comes up. I can still type and submit, but the labelText doesn't disappear like it's supposed to and most importantly, FocusManager.instance.primaryFocus?.unfocus() doesn't let the keyboard disappear.
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(5),
child: Row(
children: [
Expanded(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: Container(
margin: const EdgeInsets.only(left: 10, bottom: 10, top: 10),
child: TextField(
onTap: () => myFocusNode.requestFocus(),
decoration: const InputDecoration(
labelText: ' Enter task',
border: InputBorder.none,
floatingLabelBehavior: FloatingLabelBehavior.never,
),
controller: textController,
focusNode: myFocusNode,
onSubmitted: (_) {
submit();
myFocusNode.requestFocus();
textController.clear();
},
),
),
),
),
CircleAvatar(
child: TextButton(
onPressed: () {
submit();
myFocusNode.requestFocus();
textController.clear();
},
child: const FittedBox(
child: Text(
'Add',
style: TextStyle(
color: Colors.white,
),
),
),
),
),
],
),
);
}
I think this may be because the app is rebuilt when the soft keyboard shows up, but I'm not sure. What can I do to fix this?
I think you need to remove this:
onTap: () => myFocusNode.requestFocus(),
If you need, you can control the focus action when filed si submitted with the textInputAction property:
// Go to next field
textInputAction: TextInputAction.next
// Go to previous field
textInputAction: TextInputAction.previous
// Don't move focus
textInputAction: TextInputAction.none
// Many other possible values, check the doc ...
UPDATE
When i try your build code on a MediaPad tablet, it work like a charm, here is my implementation:
import 'package:flutter/material.dart';
class DoorMeasure extends StatefulWidget {
const DoorMeasure({Key? key}) : super(key: key);
#override
State<DoorMeasure> createState() => _DoorMeasureState();
}
class _DoorMeasureState extends State<DoorMeasure> {
var myFocusNode;
var textController = TextEditingController()..text = '';
#override
void initState() {
myFocusNode = new FocusNode();
}
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(5),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: Container(
margin: const EdgeInsets.only(left: 10, bottom: 10, top: 10),
child: TextField(
onTap: () => myFocusNode.requestFocus(),
decoration: const InputDecoration(
labelText: ' Enter task',
border: InputBorder.none,
floatingLabelBehavior: FloatingLabelBehavior.never,
),
controller: textController,
focusNode: myFocusNode,
onSubmitted: (_) {
myFocusNode.requestFocus();
textController.clear();
},
),
),
),
),
CircleAvatar(
child: TextButton(
onPressed: () {
myFocusNode.requestFocus();
textController.clear();
},
child: const FittedBox(
child: Text(
'Add',
style: TextStyle(
color: Colors.white,
),
),
),
),
),
],
),
);
}
}

Flutter AnimatedCrossFade messes up widget formatting

I'm trying to create a smooth animation using the AnimatedCrossFade widget but I noticed 2 problems:
Button dimension changes and expands during animation.
The desired outcome is that both buttons match the parent's width and that the color and text changes transition smoothly, but here's what happens.
Without AnimatedCrossFade, Button 1 looks like this:
If I wrap it inside an AnimatedCrossFade widget, Button 1 looks like this:
While the transition is happening, It looks like this:
TextField with InputDecoration stroke becomes thinner
I have multiple TextField widgets that I want to use in the page but some need to be animated in. The problem is that when I put a TextField inside an AnimatedCrossFade widget, the bottom line becomes thinner making the layout look horrible. Here's a comparison of how a TextField looks inside an AnimatedCrossFade (top) and outside of it (bottom).
This is how the layout looks after animation.
But it should look like this.
This code sample should be enough to recreate what I'm trying to explain.
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isExpanded = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView(
padding: EdgeInsets.symmetric(horizontal: 60, vertical: 60),
children: [
ElevatedButton(
child: Text(_isExpanded ? "Collapse" : "Expand"),
onPressed: () {
setState(() {
_isExpanded = !_isExpanded;
});
},
),
AnimatedCrossFade(
crossFadeState: _isExpanded
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: const Duration(seconds: 1),
firstChild: TextField(
decoration: InputDecoration(
hintText: "Text",
),
),
secondChild: SizedBox.shrink(),
),
TextField(
decoration: InputDecoration(
hintText: "Text",
),
),
AnimatedCrossFade(
crossFadeState: !_isExpanded
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: Duration(seconds: 1),
firstChild: ElevatedButton(
child: Text("Button 1"),
onPressed: () {},
),
secondChild: ElevatedButton(
child: Text("Button 2"),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
onPressed: () {},
),
),
],
),
);
}
}
Hope this is what you want?
I think to handle this case, you need to use layoutBuilder of AnimatedCrossFade
if you click on layoutBuilder you can find details.
Updated
wrap with padding to solve TextFiledFormat, for more you can use decoration.
To use max width i used like this
AnimatedCrossFade(
crossFadeState: _isExpanded
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: const Duration(seconds: 1),
firstChild: Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: TextField(
key: ValueKey("text1"),
decoration: InputDecoration(
hintText: "Text1",
),
),
),
secondChild: SizedBox.shrink(),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: TextField(
key: ValueKey("text2"),
decoration: InputDecoration(
hintText: "Text",
),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: AnimatedCrossFade(
crossFadeState: !_isExpanded
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: Duration(seconds: 1),
alignment: Alignment.center,
layoutBuilder:
(topChild, topChildKey, bottomChild, bottomChildKey) {
return topChild;
},
secondChild: ElevatedButton(
child: Text("Button 2"),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
onPressed: () {},
),
firstChild: ElevatedButton(
child: Text("Button 1"),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
onPressed: () {},
),
),
),
To get default size of button wrapped with Center inside layoutBuilder
layoutBuilder:
(topChild, topChildKey, bottomChild, bottomChildKey) {
return topChild;
},

Android like Textfield Validation in Flutter?

I would like to achieve Android like TextField validation in Flutter.
I tried the TextField docs of Flutter and the InputDecoration has a property of errorText but is displays error at the bottom of textfield. I want to achieve something like below in Flutter
You can use a TextFormField along with a custom Tooltip inside a Stack to achieve this effect. In the decoration property for the TextFormField you can use the suffixIcon property of the InputDecoration class to pass the error icon.
And you can use a bool variable to show/hide the tooltip message when the validation error occurs.
Example code for the TextFormField:
TextFormField(
decoration: InputDecoration(
//Set the different border properties for a custom design
suffixIcon: IconButton(
icon: Icon(Icons.error, color: Colors.red),
onPressed: () {
setState(() {
showTooltip = !showTooltip; //Toggles the tooltip
});
},
),
),
validator: (String value) {
if(value.isEmpty) {
setState(() {
showTooltip = true; //Toggles the tooltip
});
return "";
}
}
);
You can wrap the above code along with your custom tooltip widget code with a Stack to achieve the error tooltip effect.
Below is a quick working example. You can design your own custom tooltip widget and use it in your code.
Example:
class LoginAlternate extends StatefulWidget {
#override
_LoginAlternateState createState() => _LoginAlternateState();
}
class _LoginAlternateState extends State<LoginAlternate> {
GlobalKey<FormState> _formKey = GlobalKey();
bool showTooltip = false;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueGrey,
body: Container(
padding: EdgeInsets.symmetric(
horizontal: 100,
vertical: 100
),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Stack(
alignment: Alignment.topRight,
overflow: Overflow.visible,
children: <Widget>[
TextFormField(
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(
borderSide: BorderSide.none
),
suffixIcon: IconButton(
icon: Icon(Icons.error, color: Colors.red,),
onPressed: () {
setState(() {
showTooltip = !showTooltip;
});
},
),
hintText: "Password"
),
validator: (value) {
if(value.isEmpty) {
setState(() {
showTooltip = true;
});
return "";
}
},
),
Positioned(
top: 50,
right: 10,
//You can use your own custom tooltip widget over here in place of below Container
child: showTooltip
? Container(
width: 250,
height: 50,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all( color: Colors.red, width: 2.0 ),
borderRadius: BorderRadius.circular(10)
),
padding: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"Your passwords must match and be 6 characters long.",
),
),
) : Container(),
)
],
),
RaisedButton(
child: Text("Validate"),
onPressed: () {
_formKey.currentState.validate();
},
),
],
),
),
),
);
}
}
I think you are talking about ToolTip
You can use this library or Go through Flutter doc
new Tooltip(message: "Hello ToolTip", child: new Text("Press"));
you can use the library super_tooltip #
You can customize this type of error by using overlay widget. Error can be shown with overlay widget and that error icon can be changed using inputDecoration of TextField.
Here is the link for understanding overlay widget--
https://medium.com/saugo360/https-medium-com-saugo360-flutter-using-overlay-to-display-floating-widgets-2e6d0e8decb9

Categories

Resources