In our application, SOMETIMES space input doesn't work in textFields (f.e. adding a new message in a chat), but after refreshing the page it works again. This situation is causing unstable environment for our users and thus a lot of complaints. Is there any official documentation, or solution by flutter for this "sometimes space button cannot be used" problem. What we notices that, when this problem occurs, fonts are different than it supposed to be, like it's not loaded. It is not browser specific because problem occurs at Chrome & Edge.
The real problem is that the bug is not easy to detect because it happens only few times so i don't know how to detect and solve it.
In particular i noted that it happens only in production ( i never spotted it during development) .
Flutter doctor:
This is an example widget that have the bug
Widget build(BuildContext context) {
return CustomAlertDialog(
title: const Text(
"Aggiungi un messaggio",
style: TextStyle(fontSize: 16),
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"Annulla",
style: TextStyle(color: Colors.grey.shade700),
)),
TextButton(
onPressed: () {
},
child: const Text("Invia"))
],
content: Container(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: const EdgeInsets.only(top: 10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(16)),
border: Border.all(
color: Colors.green,
width: 2,
),
),
width: 800,
child: TextField(
minLines: 8,
maxLines: 8,
autofocus: false,
controller: _chatController,
//keyboardType: TextInputType.multiline,
onChanged: (text) {
setState(() {
textValue = text;
});
},
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(8),
hintText: "Scrivi qui il tuo messaggio",
border: InputBorder.none,
),
),
),
SizedBox(
height: 10,
),
CheckboxListTile(
value: _hiddenMessage,
onChanged: (value) {
setState(() {
_hiddenMessage = value!;
});
},
title: const Text("Nascondi"),
)
],
),
),
));
}
CustomAlertDialog:
class _CustomAlertDialogState extends State<CustomAlertDialog> {
#override
Widget build(BuildContext context) {
return AlertDialog(
insetPadding: widget.insetPadding ??
EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),
title: widget.title ??
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Icon(
Icons.cancel,
color: Colors.red,
size: 30,
),
SizedBox(width: 5),
Text('Errore'),
],
),
elevation: widget.elevation ?? 24.0,
actions: widget.actions ??
[
TextButton(
child: const Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
content: widget.content ??
const Text(
"Errore di connessione al server",
style: TextStyle(fontSize: 20),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
);
}
}
Thank you for the help!
Widget build(BuildContext context) {
return MaterialApp(
shortcuts: {
LogicalKeySet(LogicalKeyboardKey.space): ActivateIntent(),
},
title: 'title of your app',
//....
);
}
Related
this is my first time using community to ask about my project. First thing first, english isn't my first language and I'm a very beginner in flutter world. I'm trying to build my first mobile application using flutter and now I'm trying to connect my project to firebase (I looked at youtube tutorial). I don't know if the firebase already connect because when I'm trying to run the application and go to registration page, there this error message.
And here is my code:
import 'package:dfu_check_application/common/auth_controller.dart';
import 'package:flutter/material.dart';
import 'package:dfu_check_application/common/theme_helper.dart';
import 'package:dfu_check_application/pages/widgets/header_widget.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'profile_page.dart';
class RegistrationPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _RegistrationPageState();
}
}
class _RegistrationPageState extends State<RegistrationPage> {
final _formKey = GlobalKey<FormState>();
bool checkedValue = false;
bool checkboxValue = false;
#override
Widget build(BuildContext context) {
var nameController = TextEditingController();
var emailController = TextEditingController();
var passwordController = TextEditingController();
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Stack(children: [
Container(
height: 150,
child: HeaderWidget(150, false, Icons.person_add_alt_1_rounded),
),
Container(
margin: EdgeInsets.fromLTRB(25, 50, 25, 10),
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
alignment: Alignment.center,
child: Column(
children: [
Form(
key: _formKey,
child: Column(
children: [
GestureDetector(
child: Stack(
children: [
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
border:
Border.all(width: 5, color: Colors.white),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 20,
offset: const Offset(5, 5),
),
],
),
child: Icon(
Icons.person,
color: Colors.grey.shade300,
size: 80.0,
),
),
Container(
padding: EdgeInsets.fromLTRB(80, 80, 0, 0),
child: Icon(
Icons.add_circle,
color: Colors.grey.shade700,
size: 25.0,
),
),
],
),
),
SizedBox(
height: 30,
),
Container(
child: TextFormField(
controller: nameController,
decoration: ThemeHelper().textInputDecoration(
'Full Name', 'Enter your full name'),
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(
height: 30,
),
SizedBox(height: 20.0),
Container(
child: TextFormField(
controller: emailController,
decoration: ThemeHelper().textInputDecoration(
"E-mail address", "Enter your email"),
keyboardType: TextInputType.emailAddress,
validator: (val) {
// ignore: prefer_is_not_empty
if (!(val!.isEmpty) &&
!RegExp(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$")
.hasMatch(val)) {
return "Enter a valid email address";
}
return null;
},
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(height: 20.0),
Container(
child: TextFormField(
obscureText: true,
controller: passwordController,
decoration: ThemeHelper().textInputDecoration(
"Password*", "Enter your password"),
validator: (val) {
if (val!.isEmpty) {
return "Please enter your password";
}
return null;
},
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(height: 15.0),
FormField<bool>(
builder: (state) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
Checkbox(
value: checkboxValue,
onChanged: (value) {
setState(() {
checkboxValue = value!;
state.didChange(value);
});
}),
Text(
"I accept all terms and conditions.",
style: TextStyle(color: Colors.grey),
),
],
),
Container(
alignment: Alignment.centerLeft,
child: Text(
state.errorText ?? '',
textAlign: TextAlign.left,
style: TextStyle(
color: Theme.of(context).errorColor,
fontSize: 12,
),
),
)
],
);
},
validator: (value) {
if (!checkboxValue) {
return 'You need to accept terms and conditions';
} else {
return null;
}
},
),
SizedBox(height: 20.0),
GestureDetector(
onTap: () {
AuthController.instance.register(
nameController.text.trim(),
emailController.text.trim(),
passwordController.text.trim());
},
),
Container(
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: const EdgeInsets.fromLTRB(40, 10, 40, 10),
child: Text(
"Register".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => ProfilePage()),
(Route<dynamic> route) => false);
}
},
),
),
SizedBox(height: 30.0),
Text(
"Or create account using social media",
style: TextStyle(color: Colors.grey),
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
child: FaIcon(
FontAwesomeIcons.google,
size: 35,
color: HexColor("#EC2D2F"),
),
onTap: () {
setState(() {
showDialog(
context: context,
builder: (BuildContext context) {
return ThemeHelper().alartDialog(
"Google Account",
"You tap on Google icon.",
context);
},
);
});
},
),
],
),
],
),
),
],
),
),
]),
),
);
}
}
If you guys see more error on my code, please tell me because I'm very clueless about this. Thank you in advance!
The issue occurs from Stack the one inside
Column(
children: [
Form(
key: _formKey,
child: Column(
children: [
GestureDetector(
child: Stack( // this one
Can be fixed by providing hight
GestureDetector(
child: SizedBox(
height: MediaQuery.of(context).size.height, //this based on your need
child: Stack(
I think you can re struct the widget and don't need to use multi-Stack.
More about /ui/layout and Unbounded height / width
I am able to create popup dialogs using Get.defaultDialog() function. I could not find a method in GetX for creating custom alert dialogs.
I am using the function below to achieve that which uses native flutter showDialog api.
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: categoryNameController,
keyboardType: TextInputType.text,
maxLines: 1,
decoration: InputDecoration(
labelText: 'Category Name',
hintMaxLines: 1,
border: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green, width: 4.0))),
),
SizedBox(
height: 30.0,
),
RaisedButton(
onPressed: () {
if (categoryNameController.text.isNotEmpty) {
var expenseCategory = ExpenseCategory(
categoryNameController.text,
id: _addExpenseController.expenseCategories.length);
_expenseController.addExpenseCategory(expenseCategory);
_addExpenseController.expenseCategories
.add(expenseCategory);
Get.back();
}
},
child: Text(
'ADD CATEGORY',
style: TextStyle(color: Colors.white, fontSize: 16.0),
),
color: Colors.redAccent,
)
],
),
elevation: 12.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)));
});
I am able to achieve that using below function
Get.defaultDialog(
title: '',
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: settingsScreenController.categoryNameController,
keyboardType: TextInputType.text,
maxLines: 1,
decoration: InputDecoration(
labelText: 'Category Name',
hintMaxLines: 1,
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green, width: 4.0))),
),
SizedBox(
height: 30.0,
),
RaisedButton(
onPressed: () {
if (settingsScreenController
.categoryNameController.text.isNotEmpty) {
var expenseCategory = ExpenseCategory(
settingsScreenController.categoryNameController.text,
id: _addExpenseController.expenseCategories.length);
settingsScreenController.addExpenseCategory(expenseCategory);
_addExpenseController.expenseCategories.add(expenseCategory);
Get.back();
} else {
Utils.showSnackBar("Enter category name");
}
},
child: Text(
'ADD CATEGORY',
style: TextStyle(color: Colors.white, fontSize: 16.0),
),
color: Colors.redAccent,
)
],
),
radius: 10.0);
But i could not remove the title area in the dialog.
Native API dialog without title
GetX dialog api with title
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main(List<String> args) {
runApp(GetMaterialApp(
title: 'My App',
home: MyApp(),
));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Show Dialog'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
Get.defaultDialog(
);
},
child: Text('Click GetX')),
],
),
),
);
}
}
I'm working on an app that will get only 2 inputs from the user, maybe 3 in the future. So I use showDialog with 2 inputfield and 2 buttons. Very simple. Looks pretty much like this:
enter image description here
It shows up perfectly in the main screen if it's being called as a function. But I would like to use that same dialog in another screen in the app and just change the text on one of the buttons. Since the dialog code it's long and I don't want to repeat it, I want to put it in a new StatefulWidget (to retrieve the information from the input fields and clear them afterwards). Now the problem is that I can't find a way to return the dialog from an external widget. I don't know if it's actually impossible because of the whole async Widget incompatibility or I'm just too stupid to figure this out.
This is the code for my dialog (as a function):
_dialog() async {
await showDialog<String>(
context: context,
child: ButtonBarTheme(
data: ButtonBarThemeData(alignment: MainAxisAlignment.center),
child: AlertDialog(
contentPadding: const EdgeInsets.all(20.0),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.only(bottom: 15),
child: new TextField(
// onSubmitted: next,
autofocus: true,
controller: _title,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(bottom: 2),
labelText: 'Title',
hintText: 'Example: New Smartphone',
),
),
),
TextField(
autofocus: true,
controller: _codigo,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
labelText: 'Code',
hintText: 'Example: EC20008347607',
),
),
],
),
actions: [
Row(
children: [
Container(
padding: EdgeInsets.only(right: 35, bottom: 5),
child: FlatButton(
color: Colors.cyan[600],
child: const Text('CANCEL'),
onPressed: () {
Navigator.pop(context);
}),
),
Container(
padding: EdgeInsets.only(left: 15, bottom: 5),
child: FlatButton(
color: Colors.cyan[600],
child: const Text('ADD'),
onPressed: () {
setState(() {
_title.text = '';
_code.text = '';
});
Navigator.pop(context);
},
),
),
],
),
],
),
),
);
}
Thanks in advance for any help. I'm a beginner.
You can put it in another dart file that accepts any property values that aren't static, like this:
CustomAlertDialog({String leftButtonText, String rightButtonText}) async {
return AlertDialog(
contentPadding: const EdgeInsets.all(20.0),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.only(bottom: 15),
child: new TextField(
// onSubmitted: next,
autofocus: true,
controller: _title,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(bottom: 2),
labelText: 'Title',
hintText: 'Example: New Smartphone',
),
),
),
TextField(
autofocus: true,
controller: _codigo,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
labelText: 'Code',
hintText: 'Example: EC20008347607',
),
),
],
),
actions: [
Row(
children: [
Container(
padding: EdgeInsets.only(right: 35, bottom: 5),
child: FlatButton(
color: Colors.cyan[600],
child: const Text('$leftButtonText'),
onPressed: () {
Navigator.pop(context);
}),
),
Container(
padding: EdgeInsets.only(left: 15, bottom: 5),
child: FlatButton(
color: Colors.cyan[600],
child: const Text('$rightButtonText'),
onPressed: () {
setState(() {
_title.text = '';
_code.text = '';
});
Navigator.pop(context);
},
),
),
],
),
],
),
),
);
}
I think we have to build our widget from the ground up as there is no dialog box that exposes the state. Hope this helps:
https://api.flutter.dev/flutter/widgets/StatefulBuilder-class.html
Try my code snippet
**
MaterialButton(
color: Colors.blue,
height: 50,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
textColor: Colors.white,
child: Text('Show Info Dialog',),
onPressed: () {
SimpleDialogs.showinfoDialog(context: context, title: "Something insert here");
},
Below is my flutter code and I would like to make the leading calendar icon launch a calendar widget for date selection in the last textfield just before the raised button as marked below in code.
** widget starts inside stateful class**
#override
Widget build(BuildContext context) {
var db = DBHelper();
return Scaffold(
appBar: AppBar(
title: Text('Add'),
),
body: Container(
padding: EdgeInsets.only(top: 30, left: 50, right: 50),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
TextField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
icon: Icon(Icons.bookmark), hintText: 'nickname'),
controller: nameController,
),
const SizedBox(height: 15),
TextField(
decoration: InputDecoration(
icon: Icon(Icons.date_range), hintText: 'date created'),
controller: otherController,
),
const SizedBox(height: 50),
RaisedButton(
onPressed: () {
db.saveAssets(Asset(
name: nameController.text,
other: otherController.text));
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyAssetsList()),
);
},
padding: EdgeInsets.only(left: 18, right: 18),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
textColor: Colors.white,
color: Colors.lightGreen,
splashColor: Colors.lightGreenAccent,
child: const Text(
'Save',
style: TextStyle(fontSize: 20),
),
),
],
),
),
),
);
}
}
One more solution.
If you want only the calendar icon to be tapable (while still having similar design to the one you've provided):
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.date_range),
padding: EdgeInsets.zero,
onPressed: () {
print('Yay!');
},
),
Expanded(
child: TextField(
decoration: InputDecoration(
hintText: 'Date Created',
),
readOnly: true, // Or wrap the input with AbsorbPointer if you do not want the field to get highlighted by taping on it
),
),
],
)
If you want to let the user input the date by typing - just remove the readOnly attribute from the input.
I have just started learning flutter, I have a screen that contains a form, I'd like to know how to reduce the width of button and put it in center.
This the code:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ajouter note'),
centerTitle: true,
backgroundColor: Colors.pink,
),
body: Container(
padding: EdgeInsets.all(10.0),
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
TextFormField(
decoration: InputDecoration(
hintText: 'Saisir un titre',
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
SizedBox(
height: 10.0,
),
TextFormField(
minLines: 10,
maxLines: 10,
decoration: InputDecoration(
hintText: 'Saisir une déscription',
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
SizedBox(
height: 10.0,
),
RaisedButton.icon(
onPressed: () {
if (_formKey.currentState.validate()) {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Processing Data')));
}
},
label: Text(
'Enregistrer',
style: TextStyle(
fontSize: 16.0,
color: Colors.white,
),
),
icon: Icon(
Icons.save,
color: Colors.white,
),
color: Colors.pink,
),
],
),
),
),
);
}
One way could be wrapping the RaisedButton in a Padding.
You can apply padding only horizontal axis.
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: // your RaisedButton
}
There are a lot of ways of doing it. One option is to limit the size of your button like this:
Center(
child: SizedBox(
width: 100,
child: RaisedButton(
...
),
),
)