I have a flutter app which take an OTP.My issue is i have my button disable by default and want it enable when the user start inputing the otp code.
i added a value listiner to the firts otp field to be enable the button when the user starts typing the otp,but the button is disable when you finish inputing the code.i want the button to be enable when the otp field are filled.
`
class FinaliseLogin extends StatefulWidget {
FinaliseLogin({Key? key}) : super(key: key);
@override
State<FinaliseLogin> createState() => _FinaliseLoginState();
}
class _FinaliseLoginState extends State<FinaliseLogin> {
final TextEditingController _fieldOne = TextEditingController();
final TextEditingController _fieldTwo = TextEditingController();
final TextEditingController _fieldThree = TextEditingController();
final TextEditingController _fieldFour = TextEditingController();
Timer? timer;
int secondsRemaining = 30;
bool enableResend = false;
@override
initState() {
super.initState();
_fieldTwo.addListener(
() {
final isButtonDisable = _fieldTwo.text.isNotEmpty;
setState(() => this.isButtonDisable = isButtonDisable);
},
);
timer = Timer.periodic(Duration(seconds: 1), (_) {
if (secondsRemaining != 0) {
setState(() {
secondsRemaining--;
});
} else {
setState(() {
enableResend = true;
});
}
});
}
var otpsms = "";
bool isButtonDisable = false;
@override
Widget build(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.white,
),
child: Stack(
children: <Widget>[
Positioned(
top: 101,
left: 16,
right: 100,
child: Container(
height: 89,
width: 233,
child: Text(
'Verify \nPhone Number',
style: headerStyle2,
),
),
),
Positioned(
top: 350,
left: 28,
child: Row(
children: [
const Text(
"Didn't get OTP?",
style: reminderstyle,
),
TextButton(
style: TextButton.styleFrom(
foregroundColor: Color.fromARGB(255, 9, 9, 9),
),
child: Text(
'Resend OTP',
// style: resendOtpstyle,
// style: loginstyle,
),
onPressed: enableResend ? _resendCode : null,
),
Text(
'($secondsRemaining)',
style: resendOtpstyle,
),
],
),
),
Positioned(
top: 221,
left: 16,
right: 16,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
OtpInput(
_fieldOne,
),
OtpInput(
_fieldTwo,
),
OtpInput(
_fieldThree,
),
OtpInput(
_fieldFour,
)
],
),
SizedBox(
height: 80,
),
const SizedBox(
height: 40,
),
// Text(
// _otp ?? 'Please enter OTP',
// style: const TextStyle(fontSize: 30),
// ),
SubmitButton(
isDisabled: isButtonDisable,
pressed: () async {
otpsms = _fieldOne.text
_fieldTwo.text
_fieldThree.text
_fieldFour.text;
if (userObj != null) {
showModalBottomSheet(
isDismissible: false,
isScrollControlled: false,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(410),
),
),
// backgroundColor: Colors.transparent,
context: context,
builder: (context) => BottomWidget(
Headersheettext: '',
bottomsheettext:
'Your phone number has been \nverified succesfully.',
onPress: () {
if (userObj.emailAddress == null ||
userObj.emailAddress!.isEmpty ||
userObj.emailVerifiedAt.isEmpty) {
// email hasn't been verified yet
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => emailScreen()),
);
return;
}
if (userObj.vehicles == null ||
userObj.vehicles!.length == 0) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CheckThirdParty()),
);
} else {
state.updateProfile(userObj);
state.updateVehicles(userObj.vehicles!);
state.updatePolicies(policies);
Navigator.of(context)
.popUntil((route) => route.isFirst);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
DashBoard(),
),
);
}
},
),
);
}
},
title: isButtonDisable ? 'DONE' : 'PROCEED',
),
const SizedBox(
height: 30,
),
],
),
)
],
),
);
}
void _resendCode() async {
await RestClient.resendSmsotp();
setState(() {
secondsRemaining = 30;
enableResend = false;
});
}
@override
dispose() {
timer?.cancel();
super.dispose();
}
}
class OtpInput extends StatefulWidget {
late TextEditingController controller;
OtpInput(this.controller, {Key? key}) : super(key: key);
@override
State<OtpInput> createState() => _OtpInputState();
}
class _OtpInputState extends State<OtpInput> {
@override
void dispose() {
widget.controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Material(
child: SizedBox(
height: 67,
width: 78.22,
child: Column(
children: [
TextField(
// autofocus: autoFocus,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: widget.controller,
maxLength: 1,
cursorColor: Colors.transparent,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(color: Color(0xffF5F5F5)),
),
focusedBorder: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(8.0),
borderSide: BorderSide(color: Color(0xffF5F5F5)),
),
counterText: '',
hintStyle: TextStyle(
color: Colors.black,
fontSize: 20.0,
),
),
onSubmitted: null,
onChanged: (value) {
if (value.length == 1) {
FocusScope.of(context).nextFocus();
}
},
),
],
),
),
);
}
}
`
CodePudding user response:
in TextField
there is argument
onChanged: (value) {
// your code
}
You can change your state here
CodePudding user response:
write this to onchange of every textfield
if((_fieldOne.text _fieldTwo.text _fieldThree.text _fieldFour.text).isEmpty)
{
disable the button
}else{
enable the button
}