Flutter Fill in Blank with RichText - flutter

I am almost done with fill in blanks implementation for my app but unfortunately I keep running into layout issues.
However as I keep solving the issues I am almost done with it, this is the code so far:
RichText(
text: TextSpan(
text: "dummy",
style: TextStyle(
color: Colors.white,
fontSize: 20,
height: 1.5,
fontWeight: FontWeight.bold),
children: <InlineSpan>[
TextSpan(
text:
' to to to to gdfgdfgdf to to to to to to to ',
style: TextStyle(
height: 1.0,
color: Colors.grey,
fontSize: 20,
fontWeight: FontWeight.bold)),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: SecretWord("turtle"),
),
TextSpan(
text:
' to to to to gdfgdfgdf to to to to to to to ',
style: TextStyle(
height: 1.0,
color: Colors.grey,
fontSize: 20,
fontWeight: FontWeight.bold)),
)
And my SecretWord class:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
class SecretWord extends StatelessWidget {
final String answer;
int answerLength;
String answerHint;
double answerWidth;
SecretWord(this.answer){
this.answerLength = answer.length;
this.answerHint = '.' * answerLength;
this.answerWidth = this.answerLength * 15.0;
}
String value = "";
#override
Widget build(BuildContext context) {
return Container(
//alignment: Alignment.bottomCenter,
width: answerWidth,
height: null,
// margin: const EdgeInsets.only(right: 10, left: 10),
child: TextFormField(
maxLines: null,
cursorColor: Colors.cyanAccent,
cursorRadius: Radius.circular(12.0),
cursorWidth: 2.0,
style: TextStyle(
color: (value == answer) ? Colors.amberAccent : Colors.lightGreenAccent,
fontWeight: FontWeight.bold,
fontSize: 20,
letterSpacing: 3,
// height: 0.5,
),
//textAlign: TextAlign.left,
autofocus: false,
maxLength: answerLength,
onChanged: (text) {
value = text;
},
decoration: new InputDecoration(
//labelText: 'Name *',
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
counterText: '',
hintText: answerHint,
hintStyle: TextStyle(
color: Colors.lightGreenAccent,
fontWeight: FontWeight.bold,
letterSpacing: 4,
// height: 0.5,
),
)
)
);
}
}
Unfortunately this create some issues: the container height of SecretWord is superior to TextSpan, how could I succeed to reduce the height of the Container with TextFormField to match the height of TextSpan ?
Notice that the second line has more space with first and third line than what I was expecting, it is because SecretWord is considered to take more space vertically. I know the cause but not how to solve it.

Hello I've come up with a solution to reduce the inner padding of TextField/TextFormField which looks like your problem.
Setting these values for the InputDecoration of the TextField should remove the vertical padding:
TextFormField(
decoration: InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.symmetric(vertical: -5),
counterText: '',
),
)
isDense=true makes the input is part of dense form (i.e., uses less vertical
/// space).
setting contentPadding: const EdgeInsets.symmetric(vertical: -5) will reduce the vertical padding
As you already did in your example counterText: '' will prevent the counter text being shown.
So here is your new SecretWordClass with the changes. I also moved the properties under the build method since stateless widgets are immutable and their properties should be final.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
class SecretWord extends StatelessWidget {
final String answer;
SecretWord(this.answer);
#override
Widget build(BuildContext context) {
String value = "";
int answerLength = answer.length;
String answerHint = '.' * answerLength;
double answerWidth = answerLength * 15.0;
return Container(
width: answerWidth,
height: null,
child: TextFormField(
maxLines: null,
cursorColor: Colors.cyanAccent,
cursorRadius: Radius.circular(12.0),
cursorWidth: 2.0,
style: TextStyle(
color:
(value == answer) ? Colors.amberAccent : Colors.lightGreenAccent,
fontWeight: FontWeight.bold,
fontSize: 20,
letterSpacing: 3,
),
autofocus: false,
maxLength: answerLength,
onChanged: (text) {
value = text;
},
decoration: new InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.symmetric(vertical: -5),
counterText: '',
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
hintText: answerHint,
hintStyle: TextStyle(
color: Colors.lightGreenAccent,
fontWeight: FontWeight.bold,
letterSpacing: 4,
),
),
),
);
}
}
Here are the results:

Related

DropdownSearch Flutter - Font too big

I have the following code for the dropdownSearch in Flutter
However, the font is fixed and does not change when I change the screen size
enter image description here
DropdownSearch<String>(
items: items,
showSearchBox: showSearchBox ?? false,
dropdownSearchDecoration: InputDecoration(
contentPadding: const EdgeInsets.only(right: 8.0, left: 8.0),
floatingLabelStyle:
kResponsiveTextUbuntuFont(context, kDarkGreyColor),
labelText: labelTxt,
labelStyle: kResponsiveTextUbuntuFont(context, kDarkGreyColor),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: kDarkGreyColor, width: 2),
),
border: const OutlineInputBorder(
borderSide: BorderSide(color: kDarkGreyColor, width: 2),
),
),
onChanged: (newItem) => {},
showSelectedItems: true,
selectedItem: selectedItem,
popupBackgroundColor: kBackgroundColor,
dropdownSearchBaseStyle:
kResponsiveTextUbuntuFont(context, kDarkGreyColor),
mode: Mode.MENU,
),
Font:
TextStyle KResponsiveTitleUbuntuFont(BuildContext context, Color color) {
return TextStyle(
fontFamily: 'Ubuntu',
fontSize:
(setWidth(context, 0.001) >= 1) ? 30 * setWidth(context, 0.001) : 50,
fontWeight: FontWeight.w100,
wordSpacing: 5,
color: color);
}
I always find the solution directly after asking my own question xD...
Here's the solution:
Widget _customDropDownText(BuildContext context, String? name) {
return Container(
child: Text(
name.toString(),
style: kResponsiveTextUbuntuFont(context, kDarkGreyColor),
),
);
}
Build:
#override
Widget build(BuildContext context) {
.
.
.
DropdownSearch<String>(
items: widget.items,
dropdownBuilder: _customDropDownText,
showSearchBox: widget.showSearchBox ?? false,
.
.
.
}
solution

Flutter Textformfield should be responsive to typing and error

I've often seen where fields are responsive when users are typing, giving realtime feedback. An example is when I'm typing confirm password or email, if the confirm password or email hasn't matched the password while typing it returns error by marking turning the border of the field red until it matches the correct input. I have written this code, how do I improve the code to be responsive as described.
Widget _buildConfirmPasswordTF() {
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
// Text('Password', style: kLabelStyle,),
SizedBox(height: 10.0),
Container(alignment: Alignment.centerLeft, decoration: kBoxDecorationStyle, height: 60.0, child: TextFormField(
validator: ( confirmPassword ){
if ( confirmPassword.trim() != _password.isValidPassword ) {
return null;
} else {
return 'Password doesn\'t match';
}
},
obscureText: true, style: TextStyle(color: Colors.white, fontFamily: 'OpenSans',),
decoration: InputDecoration(border: InputBorder.none, contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(Icons.lock, color: Colors.white,),
hintText: 'Enter Confirm Password',
hintStyle: kHintTextStyle,
errorBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.red ) ),
focusedErrorBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.red ) )
),
),
),
],
);
}
This is where I set the hintText
final kHintTextStyle = TextStyle(
color: Colors.white54,
fontFamily: 'OpenSans',
);
This is where I set the labelStyle
final kLabelStyle = TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
);
This is where I set the border decoration
final kBoxDecorationStyle = BoxDecoration(
color: Color(0xFF6CA8F1),
borderRadius: BorderRadius.circular(10.0),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 6.0,
offset: Offset(0, 2),
),
],
);
you need autovalidateMode: AutovalidateMode.onUserInteraction, pass this in textformfield.
You can do that with a Form() providing it a key and a autoValidateMode to make sure the fields have value or that the value is something you except, you can add another field to confirm the passwork or email and compare the value of the field in the onChanged with the value of the other email field to make sure they match.
import 'package:email_validator/email_validator.dart';
final formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
bool isValid = false;
_emailController.addListener(
() {
//With this, you can "listen" all the changes on your text while
//you are typing on input
//use setState to rebuild the widget
if (EmailValidator.validate(_emailController.text)) {
setState(() {
isValid = true;
});
} else {
setState(() {
isValid = false;
});
}
},
);
Form(
key: formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.105),
child: TextFormField(
validator: (value) =>
!EmailValidator.validate(value)
? 'Enter a valid email'
: null,
keyboardType: TextInputType.emailAddress,
textAlign: TextAlign.center,
controller: _emailController,
decoration: kInputDecoration.copyWith(
hintText: 'Enter your email'),
),
),
SizedBox(
height: 18,
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.105),
child: TextFormField(
obscureText: true,
validator: (value) =>
value.isEmpty ? 'Enter your password' : null,
keyboardType: TextInputType.text,
textAlign: TextAlign.center,
controller: _passwordController,
decoration: kInputDecoration.copyWith(
hintText: 'Enter your password'),
),
),
],
),
),

Autofocus reset to the beginning of textfield

When I load (build) the page I have to focus on a textFormField that already has input, but the cursos goes to the beginning of the textfield instead of going to the end of the input.
var _tCelular = TextEditingController();
my init()
_tCelular.text = "41";
Container txtCelular1() {
return Container(
margin: EdgeInsets.only(top: 16),
child: TextFormField(
controller: _tCelular,
autofocus: true,
style: TextStyle(
color: Colors.deepOrange,
fontSize: 18,
),
decoration: InputDecoration(
labelText: 'Celular',
hintText: '(__) _ ____-____',
labelStyle: TextStyle(
color: Colors.grey, fontSize: 18, fontWeight: FontWeight.bold),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(22),
),
errorStyle: TextStyle(fontSize: 18),
suffixIcon: IconButton(
onPressed: () {
_onTapBuscarDadosCliente();
},
icon: Icon(Icons.search),
),
),
focusNode: _focusNodeFone,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
TelefoneInputFormatter(),
],
),
);
}
Since no one was able to help me, I found the answer.
I just had to add _tCelular.selection = TextSelection.collapsed(offset: _tCelular.text.length); after _tCelular.text = "41";
So, my initState is like:
_tCelular.text = ddd;
_tCelular.selection = TextSelection.collapsed(offset: _tCelular.text.length);
That worked for me.

Flutter typeahead showing all suggestions ontap field (UNWANTED)

I am using the typeahead package for flutter to show a textfield with the suggestions capability, but I am getting unwanted behavior. When the user first tap the field, I do not want to show any suggestions but it's showing a list of all suggestions like a dropdown field. I have even set getImmediateSuggestion: false but it's still doing this[![enter image description here][1]][1]
alignment: Alignment.center,
//padding: EdgeInsets.symmetric(vertical: 16),
//height: (0.0725 * y),
child: TypeAheadFormField(
keepSuggestionsOnLoading: false,
hideOnEmpty: true,
hideOnLoading: true,
//initialValue: '',
enabled: false,
hideOnError: true,
textFieldConfiguration: TextFieldConfiguration(
//textAlign: TextAlign.left,
//autofocus: true,
controller: _typeAheadController,
style: TextStyle(color: mainTextColor, fontSize:14, fontWeight: FontWeight.w400 ),
decoration: InputDecoration(
filled: true,
fillColor: cardColor,
labelStyle: TextStyle(fontSize: (0.04*x), color: mainTextColor, fontWeight: FontWeight.w400),
hintText: 'Type degree',
hintStyle: TextStyle(fontSize: (14), color: hintColor, fontWeight: FontWeight.w400),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
borderSide: BorderSide.none),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
borderSide: BorderSide(color: hintColor, width: 0.8)
)
),
),
//suggestionsBoxController: ,
getImmediateSuggestions: false,
suggestionsCallback: (pattern){
return DegreeSearchService(uni: currentUniversity).getSuggestions(pattern);
},
itemBuilder: (context, suggestion){
return ListTile(
dense: true,
title: Text(suggestion, style: TextStyle(fontSize: 14,color: Colors.black),)
);
},
onSuggestionSelected: (suggestion){
_typeAheadController.text = suggestion;
currentDegree = suggestion;//enable next press
//pageController.animateToPage(++currentPage, duration: Duration(milliseconds: 250), curve: Curves.bounceInOut );
}
)
), ```
[1]: https://i.stack.imgur.com/FUXjl.png
Try to change your suggestionsCallback to not show results if the pattern length is 0, for example:
suggestionsCallback: (pattern){
if (pattern.length > 1) {
return DegreeSearchService(uni:currentUniversity).getSuggestions(pattern);
}
},

How i can put (true icon) while i writing email and verifying from it with flutter

How I can put the icon while typing the email to verifying from email regex and the strength of the password?
TextFormField(
controller: _emailController,
textAlign: TextAlign.end,
decoration: InputDecoration(
hintStyle: TextStyle(fontSize: 16),
hintText: "example#gmail.com",
fillColor: Colors.grey[200],
filled: true,
border: OutlineInputBorder(
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
borderRadius: BorderRadius.circular(14))),
onSaved: (String value) {
email = value;
},
validator: _validateEmail,
keyboardType: TextInputType.emailAddress,
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 20, 0),
child: Text(
"كلمة المرور",
textAlign: TextAlign.right,
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16),
),
),
new TextFormField(
controller: _passwordController,
textAlign: TextAlign.end,
keyboardType: TextInputType.visiblePassword,
decoration: InputDecoration(
prefixIcon: new GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child: Padding(
padding:
const EdgeInsets.fromLTRB(20, 10, 0, 0),
child: Icon(
_obscureText
? Icons.visibility
: Icons.visibility_off,
color: visi),
)),
hintStyle: TextStyle(fontSize: 16),
hintText: "",
fillColor: Colors.grey[200],
filled: true,
border: OutlineInputBorder(
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
borderRadius: BorderRadius.circular(14))),
onSaved: (String value) {
password = value;
},
validator: _validatePassword,
obscureText: !_obscureText,
),
For email, you can add a listener to your _emailController like:
var _myIcon = Icon.cancel;
void initState() {
super.initState();
// Start listening to changes.
_emailController.addListener(_checkEmail);
}
And then:
_checkEmail() {
bool emailValid = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(_emailController.text);
if(emailValid)
setState(() {
_myIcon=Icons.ok;
});
}
Now add a prefixIcon to your email field with _myIcon value.
For a password with :
Minimum 1 Upper case
Minimum 1 lowercase
Minimum 1 Numeric Number
Minimum 1 Special Character
Common Allow Character ( ! # # $ & * ~ )
and based on this answer you can use a Regex like this:
RegExp(r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!##\$&*~]).{8,}$').hasMatch(_passwordController.text);