Flutter TextField widgets are fundamental components in any Flutter application that requires user input. In the Flutter framework, TextField widgets provide a versatile way to collect text from users. This comprehensive guide explores Flutter TextField capabilities, customization options, and best practices for implementing TextField widgets in your Flutter projects.
The Flutter TextField widget is a powerful input control that allows users to enter text into your Flutter application. This versatile Flutter TextField widget serves as the foundation for forms, search bars, messaging interfaces, and any feature requiring text input in Flutter. The Flutter TextField is one of the most commonly used input widgets in Flutter development.
TextField(
decoration: InputDecoration(
labelText: 'Username',
hintText: 'Enter your username',
border: OutlineInputBorder(),
),
)
A Flutter TextField widget comes with numerous properties that control the Flutter TextField appearance and behavior. The most common Flutter TextField properties include:
While the Flutter TextField provides basic functionality, the Flutter TextFormField extends these Flutter TextField capabilities with form validation features. The Flutter TextFormField is especially useful when working with Flutter's Form widget to manage multiple TextField inputs in your Flutter application.
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
if (!value.contains('@')) {
return 'Please enter a valid email';
}
return null;
},
)
The validator property accepts a function that returns an error message when validation fails or null when validation succeeds. This enables real-time feedback to users about input requirements.
The InputDecoration class offers extensive customization options for Flutter TextField widgets. You can enhance your Flutter TextField appearance with these Flutter TextField decoration options:
TextField(
decoration: InputDecoration(
labelText: 'Full Name',
hintText: 'Enter your full name',
prefixIcon: Icon(Icons.person),
suffixIcon: Icon(Icons.clear),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1.0),
borderRadius: BorderRadius.circular(10.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green, width: 2.0),
borderRadius: BorderRadius.circular(10.0),
),
),
)
Key decoration elements include:
The TextEditingController is crucial for managing Flutter TextField content programmatically. Every Flutter TextField should have a controller to fully utilize the Flutter TextField capabilities:
final TextEditingController _controller = TextEditingController();
@override
void initState() {
super.initState();
_controller.text = 'Initial text';
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextField(
controller: _controller,
onChanged: (text) {
print('Current text: $text');
},
);
}
The controller allows you to:
Always dispose of controllers when they're no longer needed to prevent memory leaks.
Flutter TextField widgets offer several callbacks to respond to user interactions with your Flutter TextField components:
TextField(
onChanged: (value) {
// Called whenever the text changes
print('Text changed to: $value');
},
onSubmitted: (value) {
// Called when the user submits the field (e.g., presses enter)
print('Submitted: $value');
},
onTap: () {
// Called when the user taps on the text field
print('Text field tapped');
},
)
These callbacks enable dynamic responses to user input, such as real-time filtering, validation, or auto-completion.
Effective Flutter TextField validation improves user experience by providing immediate feedback in your Flutter TextField components:
// Pattern matching using regular expressions
bool isValidEmail(String email) {
return RegExp(r'^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$').hasMatch(email);
}
// Length validation
bool isValidPassword(String password) {
return password.length >= 8;
}
// Custom validation logic
String? validateUsername(String? username) {
if (username == null || username.isEmpty) {
return 'Username cannot be empty';
}
if (username.length < 4) {
return 'Username must be at least 4 characters';
}
if (!RegExp(r'^[a-zA-Z0-9_]+$').hasMatch(username)) {
return 'Username can only contain letters, numbers and underscore';
}
return null;
}
Flutter TextField provides various keyboard types to optimize input for different data types in your Flutter TextField implementations:
// For email addresses
TextField(keyboardType: TextInputType.emailAddress)
// For numbers
TextField(keyboardType: TextInputType.number)
// For phone numbers
TextField(keyboardType: TextInputType.phone)
// For URLs
TextField(keyboardType: TextInputType.url)
// For multiline text
TextField(
keyboardType: TextInputType.multiline,
maxLines: null, // Allows unlimited lines
)
Selecting the appropriate keyboard type improves user experience by presenting relevant keys for the expected input.
Create distinctive Flutter TextField widgets with custom Flutter TextField styling options:
TextField(
style: TextStyle(
color: Colors.blue,
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
cursorColor: Colors.red,
cursorWidth: 3.0,
cursorRadius: Radius.circular(3.0),
decoration: InputDecoration(
filled: true,
fillColor: Colors.grey[200],
hoverColor: Colors.lightBlue[50],
focusColor: Colors.lightBlue[100],
// Other decoration properties
),
)
Implement secure password input with visibility toggle using Flutter TextField obscureText property:
class PasswordField extends StatefulWidget {
@override
_PasswordFieldState createState() => _PasswordFieldState();
}
class _PasswordFieldState extends State<PasswordField> {
bool _obscureText = true;
@override
Widget build(BuildContext context) {
return TextField(
obscureText: _obscureText,
decoration: InputDecoration(
labelText: 'Password',
suffixIcon: IconButton(
icon: Icon(_obscureText ? Icons.visibility : Icons.visibility_off),
onPressed: () {
setState(() {
_obscureText = !_obscureText;
});
},
),
),
);
}
}
Create a functional search field with these Flutter TextField components for search implementation:
TextField(
controller: _searchController,
decoration: InputDecoration(
labelText: 'Search',
hintText: 'Enter search terms...',
prefixIcon: Icon(Icons.search),
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: () {
_searchController.clear();
// Reset search results
},
),
),
onChanged: (value) {
// Filter results based on search term
_filterResults(value);
},
)
For longer text input requirements, configure your Flutter TextField with these properties:
TextField(
maxLines: null, // Unlimited lines
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
decoration: InputDecoration(
labelText: 'Description',
alignLabelWithHint: true, // Ensures label is aligned with the first line
border: OutlineInputBorder(),
),
)
Manage focus between multiple Flutter TextField widgets with Flutter TextField focus nodes:
final FocusNode _emailFocus = FocusNode();
final FocusNode _passwordFocus = FocusNode();
@override
void dispose() {
_emailFocus.dispose();
_passwordFocus.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
focusNode: _emailFocus,
decoration: InputDecoration(labelText: 'Email'),
textInputAction: TextInputAction.next,
onSubmitted: (_) {
FocusScope.of(context).requestFocus(_passwordFocus);
},
),
TextField(
focusNode: _passwordFocus,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
onSubmitted: (_) {
// Handle form submission
},
),
],
);
}
Format text as users type in your Flutter TextField widgets:
// Using TextInputFormatter for specific patterns
TextField(
inputFormatters: [
FilteringTextInputFormatter.digitsOnly, // Only allow digits
LengthLimitingTextInputFormatter(10), // Limit to 10 characters
],
)
// Custom formatter for phone numbers
TextField(
keyboardType: TextInputType.phone,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
TextInputFormatter.withFunction((oldValue, newValue) {
final text = newValue.text;
if (text.isEmpty) return newValue;
// Format as: (123) 456-7890
String formatted = '';
int index = 0;
if (text.length > 0) {
formatted += '(';
for (int i = 0; i < math.min(3, text.length); i++) {
formatted += text[index++];
}
}
if (text.length > 3) {
formatted += ') ';
for (int i = 0; i < math.min(3, text.length - 3); i++) {
formatted += text[index++];
}
}
if (text.length > 6) {
formatted += '-';
for (int i = 0; i < math.min(4, text.length - 6); i++) {
formatted += text[index++];
}
}
return TextEditingValue(
text: formatted,
selection: TextSelection.collapsed(offset: formatted.length),
);
}),
],
)