I am trying to get the UI of an OTP screen using flutter, but I am having errors on the FocusScope.of(context) lines. I thought the 'BuildContext context' defined for the class 'OtpPage' should have made this not an issue.
Here is the code;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '/routes/route.dart' as route;
class OtpPage extends StatelessWidget {
const OtpPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(15.0),
child: AppBar(
elevation: 0,
flexibleSpace: Container(
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage('assets/pattern.png'), fit: BoxFit.fill),
),
),
),
),
body: Container(
child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(47, 26, 47, 75),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/logo4.png',
height: 50,
),
],
),
SizedBox(height: 26),
Row(
children: [
Text(
'Enter OTP',
style: GoogleFonts.inter(
textStyle: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 24,
),
),
),
],
),
SizedBox(height: 28),
Form(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_textFieldOTP(first: true, last: false),
_textFieldOTP(first: false, last: false),
_textFieldOTP(first: false, last: false),
_textFieldOTP(first: false, last: false),
_textFieldOTP(first: false, last: true),
],
),
SizedBox(height: 34),
Container(
height: 45,
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
onPressed: () => Navigator.pushNamed(context, route.resetPassword),
style: ElevatedButton.styleFrom(primary: Color(0xFFFF2957), elevation: 0.0, shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(8.0))),
child: Text(
'Verify',
style: GoogleFonts.inter(
textStyle: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 15,
),
),
),
),
),
],
),
),
],
),
),
),
);
}
Widget _textFieldOTP({required bool first, last}) {
return Container(
height: 60,
width: 52,
child: AspectRatio(
aspectRatio: 1.0,
child: TextField(
autofocus: true,
onChanged: (value) {
if(value.length == 1 && last == false){
FocusScope.of(context).nextFocus();
}
if(value.length == 1 && first == false){
FocusScope.of(context).previousFocus();
}
},
showCursor: false,
readOnly: false,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
counter: Offstage(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black),
borderRadius: BorderRadius.circular(6),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.purple),
borderRadius: BorderRadius.circular(6),
),
),
),
),
);
}
}
I keep getting this error at the console; lib/views/otp.dart:103:29: Error: The getter 'context' isn't defined for the class 'OtpPage'.
- 'OtpPage' is from 'package:untitled/views/otp.dart' ('lib/views/otp.dart'). Try correcting the name to the name of an existing getter, or defining a getter or field named 'context'. FocusScope.of(context).nextFocus();
Same error too for the line FocusScope.of(context).previousFocus();
CodePudding user response:
you have to pass the context to the widget.Try below code,
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '/routes/route.dart' as route;
class OtpPage extends StatelessWidget {
const OtpPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(15.0),
child: AppBar(
elevation: 0,
flexibleSpace: Container(
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage('assets/pattern.png'), fit: BoxFit.fill),
),
),
),
),
body: Container(
child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(47, 26, 47, 75),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/logo4.png',
height: 50,
),
],
),
SizedBox(height: 26),
Row(
children: [
Text(
'Enter OTP',
style: GoogleFonts.inter(
textStyle: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 24,
),
),
),
],
),
SizedBox(height: 28),
Form(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_textFieldOTP(context:context,first: true, last: false),
_textFieldOTP(context:context,first: false, last: false),
_textFieldOTP(context:context,first: false, last: false),
_textFieldOTP(context:context,first: false, last: false),
_textFieldOTP(context:context,first: false, last: true),
],
),
SizedBox(height: 34),
Container(
height: 45,
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
onPressed: () => Navigator.pushNamed(context, route.resetPassword),
style: ElevatedButton.styleFrom(primary: Color(0xFFFF2957), elevation: 0.0, shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(8.0))),
child: Text(
'Verify',
style: GoogleFonts.inter(
textStyle: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 15,
),
),
),
),
),
],
),
),
],
),
),
),
);
}
Widget _textFieldOTP({required BuildContext context,required bool first, last}) {
return Container(
height: 60,
width: 52,
child: AspectRatio(
aspectRatio: 1.0,
child: TextField(
autofocus: true,
onChanged: (value) {
if(value.length == 1 && last == false){
FocusScope.of(context).nextFocus();
}
if(value.length == 1 && first == false){
FocusScope.of(context).previousFocus();
}
},
showCursor: false,
readOnly: false,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
counter: Offstage(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black),
borderRadius: BorderRadius.circular(6),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.purple),
borderRadius: BorderRadius.circular(6),
),
),
),
),
);
}
}
CodePudding user response:
Pass the context object as an argument to you _textFieldOTP method. If not, the context object to refer to in the function will not be found. See below:
Widget _textFieldOTP(BuildContext context, {required bool first, last}) {
return Container(
height: 60,
width: 52,
child: AspectRatio(
aspectRatio: 1.0,
child: TextField(
autofocus: true,
onChanged: (value) {
if(value.length == 1 && last == false){
FocusScope.of(context).nextFocus();
}
if(value.length == 1 && first == false){
FocusScope.of(context).previousFocus();
}
},
showCursor: false,
readOnly: false,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
counter: Offstage(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black),
borderRadius: BorderRadius.circular(6),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.purple),
borderRadius: BorderRadius.circular(6),
),
),
),
),
);
}
}
Then you pass the context object from the build method when calling the function _textFieldOTP
as shown below:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_textFieldOTP(context, first: true, last: false),
_textFieldOTP(context, first: false, last: false),
_textFieldOTP(context, first: false, last: false),
_textFieldOTP(context, first: false, last: false),
_textFieldOTP(context, first: false, last: true),
],
)