TextFields are fundamental UI elements in Flutter applications, serving as the primary means for users to input text. Flutter provides a variety of customization options to enhance TextField functionality, including input formatters. Input formatters enable developers to control the format of text entered by users, ensuring that it conforms to specific requirements. In this comprehensive guide, we delve into advanced TextField customization using input formatters in Flutter.
What are Input Formatters?
Input formatters are classes that transform text as it is entered into a TextField. They can be used to enforce specific formatting rules, such as restricting input to numeric values, enforcing uppercase or lowercase, adding masks for phone numbers, or any other custom formatting requirement.
Why Use Input Formatters?
- Data Validation: Enforce specific input patterns and validate user input in real-time.
- Improved User Experience: Guide users by automatically formatting text as they type.
- Data Consistency: Ensure data conforms to predefined standards and patterns.
How to Implement Input Formatters in Flutter
To implement input formatters, follow these steps:
Step 1: Create a TextEditingController
Associate a TextEditingController with your TextField to manage and control the text input:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class InputFormatterExample extends StatefulWidget {
@override
_InputFormatterExampleState createState() => _InputFormatterExampleState();
}
class _InputFormatterExampleState extends State {
final TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Input Formatter Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'Enter text',
border: OutlineInputBorder(),
),
inputFormatters: [
// Input formatters go here
],
),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Step 2: Implement Specific Input Formatters
Here are a few examples of common input formatters:
A. Numeric Input Formatter
Restricts input to numeric values:
FilteringTextInputFormatter.digitsOnly
Usage:
TextField(
controller: _controller,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Enter numbers only',
border: OutlineInputBorder(),
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
)
B. Uppercase Input Formatter
Transforms input to uppercase:
class UppercaseInputFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
return TextEditingValue(
text: newValue.text.toUpperCase(),
selection: newValue.selection,
);
}
}
Usage:
TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'Enter uppercase text',
border: OutlineInputBorder(),
),
inputFormatters: [
UppercaseInputFormatter(),
],
)
C. Lowercase Input Formatter
Transforms input to lowercase:
class LowercaseInputFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
return TextEditingValue(
text: newValue.text.toLowerCase(),
selection: newValue.selection,
);
}
}
Usage:
TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'Enter lowercase text',
border: OutlineInputBorder(),
),
inputFormatters: [
LowercaseInputFormatter(),
],
)
D. Masked Input Formatter (Phone Number)
Formats input to match a specific pattern, such as a phone number:
import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';
final maskFormatter = MaskTextInputFormatter(
mask: '(###) ###-####',
filter: { "#": RegExp(r'[0-9]') },
type: MaskAutoCompletionType.lazy
);
Usage:
TextField(
controller: _controller,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
labelText: 'Enter phone number',
border: OutlineInputBorder(),
),
inputFormatters: [
maskFormatter,
],
)
Make sure to add mask_text_input_formatter
to your pubspec.yaml
:
dependencies:
mask_text_input_formatter: ^3.0.0
E. Custom Formatting
For more complex formatting needs, you can create custom input formatters:
class CustomInputFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
String formattedText = newValue.text.replaceAll(RegExp(r'[^a-zA-Z0-9\s]'), ''); // Allow only alphanumeric and space
return TextEditingValue(
text: formattedText,
selection: newValue.selection,
);
}
}
Usage:
TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'Enter alphanumeric text',
border: OutlineInputBorder(),
),
inputFormatters: [
CustomInputFormatter(),
],
)
Combining Multiple Input Formatters
You can combine multiple input formatters to enforce different rules simultaneously:
TextField(
controller: _controller,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Enter positive numbers only',
border: OutlineInputBorder(),
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
FilteringTextInputFormatter.allow(RegExp(r'[1-9][0-9]*')), // Positive numbers only
],
)
Example: Currency Input Formatter
Let’s create a currency input formatter that formats the input as currency:
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
class CurrencyInputFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
String newText = newValue.text.replaceAll(RegExp(r'[^0-9]'), ''); // Allow only digits
if (newText.isNotEmpty) {
double value = double.parse(newText) / 100;
final formatter = NumberFormat("#,##0.00", "en_US");
newText = formatter.format(value);
}
return TextEditingValue(
text: newText,
selection: TextSelection.collapsed(offset: newText.length),
);
}
}
Usage:
TextField(
controller: _controller,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Enter amount',
prefixText: '\$ ',
border: OutlineInputBorder(),
),
inputFormatters: [
CurrencyInputFormatter(),
],
)
Don’t forget to add the intl
dependency to your pubspec.yaml
file:
dependencies:
intl: ^0.17.0
Conclusion
Advanced TextField customization using input formatters is a powerful technique in Flutter for validating and formatting user input. By leveraging input formatters, developers can enforce data consistency, improve user experience, and validate input in real-time. Whether it’s numeric input, uppercase conversion, or masked formatting, input formatters provide the flexibility to handle various formatting needs effectively.