1
I am with a plugin to select the country code and a TextFormField
to enter the email/mobile. I have a variable to display or not this CountryCode
.
The problem is that when typing a number in the TextFormField
the _isNumber
switches to true the CountryCode
appears, the TextFormField
continues with the focus, but the keyboard disappears. How do I focus on email/mobile and the keyboard activated?
import 'package:country_code_picker/country_code_picker.dart';
import 'package:ebonus_app/controllers/auth_controller.dart';
import 'package:ebonus_app/utils/app_routes.dart';
import 'package:flutter/material.dart';
class LoginView extends StatefulWidget {
@override
_LoginViewState createState() => _LoginViewState();
}
class _LoginViewState extends State<LoginView> {
final _formKey = GlobalKey<FormState>();
final _identifierController = TextEditingController();
final _passwordController = TextEditingController();
bool _isNumber = false;
CountryCode _countryCode;
bool _isLoading = false;
FocusNode _focusNodeEmailPhone;
FocusNode _focusNodePassword;
final _authController = AuthController();
@override
void initState() {
super.initState();
_identifierController.addListener(_onChangeTextInput);
_focusNodeEmailPhone = FocusNode();
_focusNodePassword = FocusNode();
}
@override
void dispose() {
_focusNodeEmailPhone.dispose();
_focusNodePassword.dispose();
_identifierController.dispose();
_passwordController.dispose();
super.dispose();
}
void _onChangeTextInput() {
setState(() {
_isNumber = isNumeric(_identifierController.text);
});
}
bool isNumeric(String string) {
return double.tryParse(string) != null;
}
void changeCountryCode(CountryCode code) {
_countryCode = code;
}
void _submit() async {
if (!_formKey.currentState.validate()) {
return;
}
setState(() {
_isLoading = true;
});
String countryCode = _countryCode.toString();
countryCode = countryCode.substring(1);
String identification = _isNumber ? countryCode + '-' + _identifierController.text : _identifierController.text;
String password = _passwordController.text;
try {
await _authController.login(identification, password);
Navigator.pushReplacementNamed(context, AppRoutes.HOME);
} catch (error) {
print(error);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
children: [
Image.asset(
'assets/images/logo.png',
width: 300,
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 20,
),
child: Text(
'Acesse sua conta eBonus',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
),
),
),
],
),
Container(
margin: EdgeInsets.fromLTRB(30, 20, 30, 20),
child: Card(
elevation: 8.0,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Row(
children: [
if (_isNumber)
Expanded(
flex: 1,
child: CountryCodePicker(
onChanged: changeCountryCode,
initialSelection: 'BR',
favorite: ['+55', 'BR'],
countryFilter: ['BR', 'US'],
flagWidth: 25,
alignLeft: true,
onInit: (code) => changeCountryCode(code),
),
),
Expanded(
flex: _isNumber ? 2 : 1,
child: TextFormField(
focusNode: _focusNodeEmailPhone,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
icon: _isNumber ? null : Icon(Icons.login),
labelText: 'Digite seu celular ou email *',
),
keyboardType: TextInputType.text,
controller: _identifierController,
validator: (value) {
if (value.isEmpty) {
return 'Campo obrigatório';
}
return null;
},
),
),
],
),
TextFormField(
focusNode: _focusNodePassword,
textInputAction: TextInputAction.done,
decoration: const InputDecoration(
icon: Icon(Icons.vpn_key),
labelText: 'Senha *',
),
keyboardType: TextInputType.text,
controller: _passwordController,
obscureText: true,
validator: (value) {
if (value.isEmpty) {
return 'Campo obrigatório';
}
return null;
},
),
SizedBox(height: 30),
_isLoading
? CircularProgressIndicator()
: Container(
width: double.infinity,
child: RaisedButton(
onPressed: _submit,
color: Colors.blue,
textColor: Colors.white,
padding: EdgeInsets.symmetric(
vertical: 12,
),
child: Text('Acessar minha conta'.toUpperCase(),
style: TextStyle(
fontSize: 15,
)),
),
),
SizedBox(height: 10),
FlatButton(
onPressed: () {
Navigator.of(context).pushReplacementNamed(AppRoutes.REGISTER_CUSTOMER);
},
child: Text(
"Não possui uma conta? Crie aqui",
style: TextStyle(
color: Colors.blue,
),
),
),
FlatButton(
onPressed: () {},
child: Text(
"Esqueci minha senha",
style: TextStyle(
color: Colors.blue,
),
),
),
],
),
),
),
),
)
],
),
),
),
);
}
}
Observing: By separating Countrycode and Textformfield into two Rows the problem does not occur, but breaks down the layout it should have.
Column(
children: <Widget>[
Row(
children: [
if (_isNumber)
Expanded(
flex: 1,
child: CountryCodePicker(
onChanged: changeCountryCode,
initialSelection: 'BR',
favorite: ['+55', 'BR'],
countryFilter: ['BR', 'US'],
flagWidth: 25,
alignLeft: true,
onInit: (code) => changeCountryCode(code),
),
),
],
),
Row(
children: [
Expanded(
flex: _isNumber ? 2 : 1,
child: TextFormField(
focusNode: _focusNodeEmailPhone,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
icon: _isNumber ? null : Icon(Icons.login),
labelText: 'Digite seu celular ou email *',
),
keyboardType: TextInputType.text,
controller: _identifierController,
validator: (value) {
if (value.isEmpty) {
return 'Campo obrigatório';
}
return null;
},
),
),
],
),
Your solution worked. Can you explain to me why the way I did was wrong?
– Marcelo
@Marcelo Implementei my answer.
– Matheus Ribeiro