I am trying to create this input field for the user to register its pin, however I don't want to call another context screen. So, the point is simple, the user types the pin, the field clears, the text in the screen changes and the user types again , confirming the pin.
I ran into two problems tho. The field never clears, no matter what I do and when I click the field to type again the state resets back to the first pin input. here is the code for the widgets.
//Form fields
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Column(
children: [
Container(
width: 330,
child: pinCodeType == 1
? Text("Choose a Pincode",
style: TextStyle(color: brandBlue, fontSize: 18))
: Text("Repeat your Pincode",
style: TextStyle(color: brandBlue, fontSize: 18)),
),
Container(
height: 90,
width: 330,
child: pinCodeType == 1
? new PinCodeTextField(
enablePinAutofill: false,
keyboardAppearance: Brightness.dark,
length: 5,
obscureText: true,
textStyle: TextStyle(color: brandBlue),
animationType: AnimationType.scale,
keyboardType: TextInputType.numberWithOptions(),
autoDisposeControllers: true,
pinTheme: PinTheme(
shape: PinCodeFieldShape.underline,
//borderRadius: BorderRadius.circular(5),
fieldHeight: 80,
fieldWidth: 60,
activeColor: brandBlue,
inactiveFillColor: Colors.transparent,
inactiveColor: brandDarkGrey,
activeFillColor: brandWhite,
selectedColor: brandLightBlue,
selectedFillColor: Colors.transparent),
animationDuration: Duration(milliseconds: 300),
backgroundColor: brandWhite,
enableActiveFill: true,
errorAnimationController: errorController,
controller: textEditingController,
onCompleted: (v) {
if (pinCodeType == 1) {
pincode1 = v;
print("PINCODE 1 $pincode1");
print("PINCODE TYPE $pinCodeType");
setState(() {
textEditingController.clear();
pinCodeType = 2;
v = '';
});
}
},
onChanged: (value) {
print(value);
setState(() {});
},
beforeTextPaste: (text) {
print("Allowing to paste $text");
//if you return true then it will show the paste confirmation dialog. Otherwise if false, then nothing will happen.
//but you can show anything you want here, like your pop up saying wrong paste format or etc
return true;
},
appContext: context,
)
: new PinCodeTextField(
enablePinAutofill: false,
keyboardAppearance: Brightness.dark,
length: 5,
obscureText: true,
textStyle: TextStyle(color: brandBlue),
animationType: AnimationType.scale,
keyboardType: TextInputType.numberWithOptions(),
pinTheme: PinTheme(
shape: PinCodeFieldShape.underline,
//borderRadius: BorderRadius.circular(5),
fieldHeight: 80,
fieldWidth: 60,
activeColor: brandBlue,
inactiveFillColor: Colors.transparent,
inactiveColor: brandDarkGrey,
activeFillColor: brandWhite,
selectedColor: brandLightBlue,
selectedFillColor: Colors.transparent),
animationDuration: Duration(milliseconds: 300),
backgroundColor: brandWhite,
autoDisposeControllers: true,
enableActiveFill: true,
errorAnimationController: errorController2,
controller: textEditingController2,
onCompleted: (v) {
if (pinCodeType == 2) {
pincode1 = v;
print("PINCODE 2 $pincode2");
print("PINCODE TYPE $pinCodeType");
setState(() {
v = '';
pinCodeType++;
});
}
},
onChanged: (value) {
print(value);
setState(() {});
},
beforeTextPaste: (text) {
print("Allowing to paste $text");
//if you return true then it will show the paste confirmation dialog. Otherwise if false, then nothing will happen.
//but you can show anything you want here, like your pop up saying wrong paste format or etc
return true;
},
appContext: context,
)),
Container(
width: MediaQuery.of(context).size.width * 0.9,
child: ListTile(
title: Text(
"Use [biometric]",
style: TextStyle(color: brandBlue, fontSize: 18),
),
trailing: FlutterSwitch(
width: 70.0,
height: 30.0,
valueFontSize: 12.0,
toggleSize: 20.0,
value: biometricStatus,
activeText: "Yes",
activeTextColor: brandBlue,
inactiveText: "No",
activeColor: brandOrange,
borderRadius: 30.0,
padding: 8.0,
showOnOff: true,
onToggle: (val) {
setState(() {
biometricStatus = val;
});
},
),
)),
],
);
}),
And here is the code for the initial states
TextEditingController textEditingController = TextEditingController();
TextEditingController textEditingController2 = TextEditingController();
StreamController<ErrorAnimationType> errorController;
StreamController<ErrorAnimationType> errorController2;
bool hasError = false;
const brandBlue = const Color(0xff243665);
const brandWhite = const Color(0xffF8F8FA);
const brandLightGrey = const Color(0xffE7E9ED);
const brandMediumGrey = const Color(0xffAAB0B9);
const brandDarkGrey = const Color(0xff868E94);
const brandLightBlue = const Color(0xff0FAFDA);
const brandOrange = const Color(0xffEB684F);
bool biometricStatus = true;
String pincode1;
String pincode2;
var pinCodeType = 1;
@override
void initState() {
errorController = StreamController<ErrorAnimationType>();
textEditingController = TextEditingController();
textEditingController2 = TextEditingController();
pinCodeType = 1;
super.initState();
}
@override
void dispose() {
errorController.close();
super.dispose();
}
How do I get this right:?
You don't need to call
textEditingController.clear();
insidesetState()
to clear the value set on the TextEditingController. Move the function outside setState and this should fix the issue.