Flutter Custom TextField includes features like focus node, next node, onTap function,
void main() async {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
final TextEditingController _addressController = TextEditingController();
final TextEditingController _contactPersonNameController = TextEditingController();
final TextEditingController _contactPersonNumberController = TextEditingController();
final FocusNode _addressNode = FocusNode();
final FocusNode _nameNode = FocusNode();
final FocusNode _numberNode = FocusNode();
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Colors.blue,
fontFamily: "Lato",
),
home: Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
MyTextField(
hintText: 'Delivery address',
inputType: TextInputType.streetAddress,
focusNode: _addressNode,
nextFocus: _nameNode,
controller: _addressController,
),
MyTextField(
hintText: 'Person name',
inputType: TextInputType.name,
focusNode: _nameNode,
nextFocus: _numberNode,
controller: _contactPersonNameController,
)
],
),
),
),
);
}
}
final robotoRegular = TextStyle(
fontFamily: 'Roboto',
fontWeight: FontWeight.w400,
fontSize: 15,
);
class MyTextField extends StatefulWidget {
final String hintText;
final TextEditingController controller;
final FocusNode focusNode;
final FocusNode nextFocus;
final TextInputType inputType;
final TextInputAction inputAction;
final int maxLines;
final bool isPassword;
final VoidCallback? onTap;
final VoidCallback? onChanged;
final VoidCallback? onSubmit;
final bool isEnabled;
final TextCapitalization capitalization;
final Color? fillColor;
final bool autoFocus;
final GlobalKey<FormFieldState<String>>? key;
MyTextField(
{this.hintText = '',
required this.controller,
required this.focusNode,
required this.nextFocus,
this.isEnabled = true,
this.inputType = TextInputType.text,
this.inputAction = TextInputAction.next,
this.maxLines = 1,
this.onSubmit,
this.onChanged,
this.capitalization = TextCapitalization.none,
this.onTap,
this.fillColor,
this.isPassword = false,
this.autoFocus = false,
this.key});
@override
_MyTextFieldState createState() => _MyTextFieldState();
}
class _MyTextFieldState extends State<MyTextField> {
bool _obscureText = true;
@override
Widget build(BuildContext context) {
return TextField(
key: widget.key,
maxLines: widget.maxLines,
controller: widget.controller,
focusNode: widget.focusNode,
style: robotoRegular,
textInputAction: widget.inputAction,
keyboardType: widget.inputType,
cursorColor: Theme.of(context).primaryColor,
textCapitalization: widget.capitalization,
enabled: widget.isEnabled,
autofocus: widget.autoFocus,
//onChanged: widget.isSearch ? widget.languageProvider.searchLanguage : null,
obscureText: widget.isPassword ? _obscureText : false,
// inputFormatters: widget.inputType == TextInputType.phone ? <TextInputFormatter>[FilteringTextInputFormatter.allow(RegExp('[0-9+]'))] : null,
decoration: InputDecoration(
hintText: widget.hintText,
isDense: true,
filled: true,
fillColor: widget.fillColor != null ? widget.fillColor : Theme.of(context).cardColor,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10), borderSide: BorderSide.none),
hintStyle: robotoRegular.copyWith(color: Theme.of(context).hintColor),
suffixIcon: widget.isPassword ? IconButton(
icon: Icon(_obscureText ? Icons.visibility_off : Icons.visibility, color: Theme.of(context).hintColor.withOpacity(0.3)),
onPressed: _toggle,
) : null,
),
onTap: widget.onTap,
onSubmitted: (text) => widget.nextFocus != null ? FocusScope.of(context).requestFocus(widget.nextFocus)
: widget.onSubmit != null ? widget.onSubmit! : null,
// onChanged: widget.onChanged,
);
}
void _toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
}