phone_text_field 2.0.0 copy "phone_text_field: ^2.0.0" to clipboard
phone_text_field: ^2.0.0 copied to clipboard

A comprehensive Flutter plugin for international phone number input, validation, formatting, and country selection with localization support.

📱 Phone Text Field #

Pub Version Flutter Platform License GitHub Stars

A comprehensive Flutter package for international phone number input with validation, formatting, and country selection. Perfect for apps requiring phone number collection with proper validation and beautiful UI.

🚀 Live Demo #

🌐 Try the Interactive Web Demo - Experience all features in your browser!

📱 Mobile Demo: Clone and run the example app to see it in action on mobile devices.

✨ Demo #

Phone Text Field Demo

🎯 Key Features #

🌍 International Support #

  • 200+ countries with proper validation rules
  • Automatic formatting based on country standards
  • Real-time validation with visual feedback
  • Smart country detection from phone numbers

🎨 Customizable UI #

  • Material 3 Design support
  • Dark/Light theme compatibility
  • Flexible styling options
  • Custom decorations for input fields
  • Responsive design for web and mobile

🔧 Developer-Friendly #

  • TextEditingController support for form integration
  • Validation callbacks with custom error messages
  • Localization support (Arabic, English, French)
  • TypeScript-like strongly typed API
  • Well-documented with comprehensive examples

🐛 Recent Bug Fixes (v1.0.0+) #

  • Fixed controller integration - Proper TextEditingController support
  • Fixed +1 country codes - US/Canada flag switching issue resolved
  • Fixed Chinese validation - Corrected 11-digit validation for China
  • Improved performance - Optimized country selection logic

📦 Installation #

1. Add Dependency #

Add this to your pubspec.yaml:

dependencies:
  phone_text_field: ^1.0.0 # Use latest version

2. Install #

flutter pub get

3. Import #

import 'package:phone_text_field/phone_text_field.dart';

🔥 Quick Start #

Basic Usage #

PhoneTextField(
  onChanged: (phoneNumber) {
    print('Complete number: ${phoneNumber.completeNumber}');
    print('Country: ${phoneNumber.countryISOCode}');
  },
)

With Controller (Form Integration) #

class MyForm extends StatefulWidget {
  @override
  _MyFormState createState() => _MyFormState();
}

class _MyFormState extends State<MyForm> {
  final _phoneController = TextEditingController();
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: PhoneTextField(
        controller: _phoneController,
        isRequired: true,
        autovalidateMode: AutovalidateMode.onUserInteraction,
        decoration: const InputDecoration(
          labelText: 'Phone Number',
          border: OutlineInputBorder(),
        ),
        onChanged: (phoneNumber) {
          // Handle phone number changes
        },
      ),
    );
  }

  @override
  void dispose() {
    _phoneController.dispose();
    super.dispose();
  }
}

🎨 Advanced Examples #

Custom Styling with Material 3 #

PhoneTextField(
  initialCountryCode: 'AE',
  decoration: const InputDecoration(
    filled: true,
    labelText: 'Phone Number',
    border: OutlineInputBorder(
      borderRadius: BorderRadius.all(Radius.circular(12)),
    ),
    prefixIcon: Icon(Icons.phone),
  ),
  searchFieldInputDecoration: const InputDecoration(
    filled: true,
    border: OutlineInputBorder(
      borderRadius: BorderRadius.all(Radius.circular(12)),
    ),
    suffixIcon: Icon(Icons.search),
    hintText: 'Search country',
  ),
  countryViewOptions: CountryViewOptions.countryCodeWithFlag,
  onChanged: (phoneNumber) {
    debugPrint('Phone: ${phoneNumber.completeNumber}');
  },
)

Arabic Localization #

PhoneTextField(
  locale: const Locale('ar'),
  decoration: const InputDecoration(
    filled: true,
    labelText: 'رقم الهاتف',
    border: OutlineInputBorder(
      borderRadius: BorderRadius.all(Radius.circular(12)),
    ),
    prefixIcon: Icon(Icons.phone),
  ),
  searchFieldInputDecoration: const InputDecoration(
    filled: true,
    border: OutlineInputBorder(
      borderRadius: BorderRadius.all(Radius.circular(12)),
    ),
    suffixIcon: Icon(Icons.search),
    hintText: 'بحث عن بالاسم او الرمز',
  ),
  dialogTitle: 'اختر الدولة',
  initialCountryCode: 'AE',
  onChanged: (phoneNumber) {
    debugPrint('رقم الهاتف: ${phoneNumber.completeNumber}');
  },
)

Validation & Error Handling #

PhoneTextField(
  isRequired: true,
  invalidNumberMessage: 'Please enter a valid phone number',
  autovalidateMode: AutovalidateMode.onUserInteraction,
  decoration: const InputDecoration(
    labelText: 'Phone Number *',
    border: OutlineInputBorder(),
    helperText: 'Enter your phone number with country code',
  ),
  onChanged: (phoneNumber) {
    if (phoneNumber.isValid) {
      print('Valid number: ${phoneNumber.completeNumber}');
    }
  },
)

Different Country Display Options #

// Flag only
PhoneTextField(
  countryViewOptions: CountryViewOptions.countryFlagOnly,
  onChanged: (phoneNumber) {},
)

// Country name with flag
PhoneTextField(
  countryViewOptions: CountryViewOptions.countryNameWithFlag,
  onChanged: (phoneNumber) {},
)

// Country code only
PhoneTextField(
  countryViewOptions: CountryViewOptions.countryCodeOnly,
  onChanged: (phoneNumber) {},
)

📋 API Reference #

PhoneTextField Properties #

Property Type Default Description
onChanged Function(PhoneNumber) required Callback when phone number changes
controller TextEditingController? null Controller for form integration
initialCountryCode String? null Initial country code (e.g., 'US', 'AE')
initialValue String? null Initial phone number value
decoration InputDecoration? null Input field decoration
searchFieldInputDecoration InputDecoration? null Country search field decoration
locale Locale? null Localization (ar, en, fr)
isRequired bool false Whether the field is required
invalidNumberMessage String? null Custom validation error message
countryViewOptions CountryViewOptions countryCodeWithFlag How to display countries
dialogTitle String? null Custom dialog title
autovalidateMode AutovalidateMode? null When to validate input

PhoneNumber Object #

class PhoneNumber {
  String completeNumber;      // Full international number
  String countryISOCode;      // Country code (US, AE, etc.)
  String countryCode;         // Dial code (+1, +971, etc.)
  String number;              // Local number
  bool isValid;               // Validation status
}

CountryViewOptions #

enum CountryViewOptions {
  countryCodeOnly,           // +1
  countryNameOnly,           // United States
  countryFlagOnly,           // 🇺🇸
  countryCodeWithFlag,       // 🇺🇸 +1
  countryNameWithFlag,       // 🇺🇸 United States
}

🔧 Integration Examples #

With Form Validation #

class PhoneForm extends StatefulWidget {
  @override
  _PhoneFormState createState() => _PhoneFormState();
}

class _PhoneFormState extends State<PhoneForm> {
  final _formKey = GlobalKey<FormState>();
  final _phoneController = TextEditingController();
  PhoneNumber? _phoneNumber;

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          PhoneTextField(
            controller: _phoneController,
            isRequired: true,
            autovalidateMode: AutovalidateMode.onUserInteraction,
            decoration: const InputDecoration(
              labelText: 'Phone Number *',
              border: OutlineInputBorder(),
            ),
            onChanged: (phoneNumber) {
              setState(() {
                _phoneNumber = phoneNumber;
              });
            },
          ),
          const SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              if (_formKey.currentState!.validate() &&
                  _phoneNumber?.isValid == true) {
                // Process valid phone number
                print('Valid phone: ${_phoneNumber!.completeNumber}');
              }
            },
            child: const Text('Submit'),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _phoneController.dispose();
    super.dispose();
  }
}

With Bloc/Provider State Management #

// Using Provider
class PhoneProvider extends ChangeNotifier {
  PhoneNumber? _phoneNumber;

  PhoneNumber? get phoneNumber => _phoneNumber;

  void updatePhone(PhoneNumber phoneNumber) {
    _phoneNumber = phoneNumber;
    notifyListeners();
  }
}

// In your widget
Consumer<PhoneProvider>(
  builder: (context, phoneProvider, child) {
    return PhoneTextField(
      onChanged: (phoneNumber) {
        phoneProvider.updatePhone(phoneNumber);
      },
    );
  },
)

🐛 Bug Fixes & Improvements #

Version 1.0.0+ Fixes #

✅ Controller Integration Issue (#2)

Problem: Controller property was commented out, causing integration issues with forms.

// Before (broken)
// final TextEditingController? controller;

// After (fixed)
final TextEditingController? controller;

✅ +1 Country Code Flag Switching (#3)

Problem: When editing US/Canada numbers, flag would incorrectly switch between countries. Solution: Improved country selection logic to preserve originally selected country when multiple countries share the same dial code.

✅ Chinese Phone Number Validation (#4)

Problem: Chinese numbers were validated as 12 digits instead of 11.

// Before
'CN': {minLength: 12, maxLength: 12}

// After
'CN': {minLength: 11, maxLength: 11}

Testing the Fixes #

You can test these fixes in the example app or the live demo:

  1. Controller Test: Use the form integration examples
  2. +1 Countries Test: Try switching between US (+1) and Canada (+1)
  3. Chinese Numbers Test: Enter a Chinese number like 13812345678

🌍 Supported Countries #

This package supports 200+ countries with proper validation rules including:

  • 🇺🇸 United States (+1)
  • 🇨🇦 Canada (+1)
  • 🇬🇧 United Kingdom (+44)
  • 🇦🇪 United Arab Emirates (+971)
  • 🇨🇳 China (+86)
  • 🇮🇳 India (+91)
  • 🇧🇷 Brazil (+55)
  • 🇩🇪 Germany (+49)
  • 🇫🇷 France (+33)
  • 🇯🇵 Japan (+81)
  • And many more...

🌐 Localization #

The package supports multiple languages:

Language Locale Status
English en ✅ Full Support
Arabic ar ✅ Full Support
French fr ✅ Full Support

Adding New Languages #

Contributions for additional languages are welcome! Check our contribution guide for details.

📱 Platform Support #

Platform Status Notes
📱 iOS ✅ Full Support iOS 9.0+
🤖 Android ✅ Full Support API 16+
🌐 Web ✅ Full Support All modern browsers
🖥️ macOS ✅ Full Support macOS 10.11+
🖥️ Windows ✅ Full Support Windows 10+
🐧 Linux ✅ Full Support Any distribution

🎯 Examples & Demos #

📱 Example App #

Run the comprehensive example app:

cd example
flutter run

🌐 Web Demo #

Experience the full demo in your browser:

cd example
flutter run -d chrome

📋 Code Examples #

📸 Screenshots #

Country Selection
🌍 Country Selection
Easy country selection with search functionality
Phone Input
📱 Phone Input
Clean phone number input with validation
Arabic Localization
🇸🇦 Arabic Localization
Full RTL support with Arabic text
Validation
✅ Validation & Error Handling
Real-time validation with error messages

🎬 Live Demo #

Phone Text Field Demo

Interactive demo showing all features in action


🎨 Key Features Grid #

International Support

🌍 International
200+ countries with proper validation rules
Customizable Design

🎨 Customizable
Material 3 design with flexible styling
Localization Support

🌐 Localized
Arabic, English, French support
Validation System

✅ Validation
Real-time validation with custom messages

� Feature Showcase #

✨ Feature 📷 Preview 📝 Description
🌍 International Country flags 200+ countries with proper validation rules
🎨 Customizable Styled input Material 3 design with flexible styling
🌐 Localized Arabic UI Arabic, English, French support
Validation Error states Real-time validation with custom messages

🤝 Contributing #

We welcome contributions! Here's how you can help:

🐛 Report Bugs #

  • Use the issue tracker
  • Include reproduction steps and Flutter/Dart versions
  • Check existing issues first

✨ Request Features #

  • Open a feature request
  • Describe the use case and expected behavior
  • Consider contributing the implementation

🔧 Submit Pull Requests #

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes and add tests
  4. Ensure all tests pass: flutter test
  5. Commit with conventional commits: git commit -m "feat: add amazing feature"
  6. Push to your fork: git push origin feature/amazing-feature
  7. Open a Pull Request

📝 Development Setup #

# Clone the repository
git clone https://github.com/MohamedAbd0/phone_text_field.git
cd phone_text_field

# Install dependencies
flutter pub get

# Run tests
flutter test

# Run example app
cd example
flutter run

📄 License #

This project is licensed under the MIT License - see the LICENSE file for details.

👨‍💻 Author #

Mohamed Abdo

⭐ Show Your Support #

If this package helped you, please:

  • Star the repository on GitHub
  • 👍 Like the package on pub.dev
  • 🐦 Share it on social media
  • 💝 Consider sponsoring the project

📊 Stats #

GitHub stars Pub points Pub popularity GitHub issues GitHub pull requests


Made with ❤️ by Mohamed Abdo

⬆ Back to Top

21
likes
150
points
1.69k
downloads

Publisher

verified publishermohamed-abdo.com

Weekly Downloads

A comprehensive Flutter plugin for international phone number input, validation, formatting, and country selection with localization support.

Repository (GitHub)
View/report issues

Topics

#phone #textfield #validation #i18n #country-picker

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

flutter, flutter_localizations

More

Packages that depend on phone_text_field