phone_input_plus 0.1.0 copy "phone_input_plus: ^0.1.0" to clipboard
phone_input_plus: ^0.1.0 copied to clipboard

A customizable phone input field with auto country detection, formatting and validation. Perfect for African and international phone numbers.

πŸ“± phone_input_plus #

A customizable Flutter phone input field with automatic country detection, smart formatting, and validation. Perfect for African and international phone numbers.

pub package pub points popularity likes License: MIT

✨ Features #

  • Auto Country Detection - Detects user's country via IP or device locale
  • Smart Formatting - Real-time number formatting as you type
  • Built-in Validation - Country-specific phone number validation
  • Highly Customizable - Extensive styling and configuration options
  • 54 African Countries - Optimized for African phone numbers
  • International Support - Works worldwide with any country
  • Multiple Selector Types - BottomSheet, Dialog, or Full Page
  • Search Functionality - Quick country search with multi-language support
  • Smart Caching - Caches detected country for better performance
  • Controller Support - Full programmatic control like TextField

πŸ“Έ Screenshots #

[] [] [] [] [] []
Basic Basic Example BottomSheet Country Controller Example Dialog Country Validation Example

πŸš€ Getting Started #

Installation #

Add this to your pubspec.yaml:

dependencies:
  phone_input_plus: ^0.0.1

Then run:

flutter pub get

Import #

import 'package:phone_input_plus/phone_input_plus.dart';

πŸ’‘ Basic Usage #

Simple Phone Input #

The most basic usage with auto country detection:

PhoneInputField(
  decoration: const InputDecoration(
    labelText: 'Phone Number',
    border: OutlineInputBorder(),
  ),
  onChanged: (PhoneNumber phone) {
    print('International: ${phone.international}');
    print('Valid: ${phone.isValid}');
  },
)

With Initial Country #

Set a specific initial country:

PhoneInputField(
  initialCountry: CountryData.benin,
  autoDetect: false, // Disable auto-detection
  decoration: const InputDecoration(
    labelText: 'Phone Number',
    border: OutlineInputBorder(),
  ),
)

Limited Country List #

Restrict to specific countries (e.g., West Africa only):

PhoneInputField(
  countries: const [
    CountryData.benin,
    CountryData.gabon,
    CountryData.senegal,
    CountryData.coteDivoire,
    CountryData.cameroon,
  ],
  decoration: const InputDecoration(
    labelText: 'Phone Number',
    border: OutlineInputBorder(),
  ),
)

🎯 Advanced Usage #

Using PhoneController #

For programmatic control, use PhoneController:

class MyWidget extends StatefulWidget {
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late PhoneController _controller;

  @override
  void initState() {
    super.initState();
    _controller = PhoneController(
      initialCountry: CountryData.benin,
    );
    
    // Listen to changes
    _controller.addListener(() {
      print('Phone changed: ${_controller.international}');
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        PhoneInputField(
          controller: _controller,
          decoration: const InputDecoration(
            labelText: 'Phone Number',
            border: OutlineInputBorder(),
          ),
        ),
        
        // Programmatic actions
        ElevatedButton(
          onPressed: () => _controller.changeCountry(CountryData.france),
          child: const Text('Switch to France'),
        ),
        ElevatedButton(
          onPressed: () => _controller.clear(),
          child: const Text('Clear'),
        ),
      ],
    );
  }
}

Form Validation #

Integrate with Flutter forms:

Form(
  key: _formKey,
  child: PhoneInputField(
    decoration: const InputDecoration(
      labelText: 'Phone Number *',
      border: OutlineInputBorder(),
    ),
    validator: (phone) {
      if (phone == null || phone.isEmpty) {
        return 'Phone number is required';
      }
      if (!phone.isValid) {
        return 'Invalid phone number for ${phone.country.nameEn}';
      }
      return null;
    },
    onSubmitted: (phone) {
      if (_formKey.currentState!.validate()) {
        // Submit form
      }
    },
  ),
)

🌍 Country Detection #

The package automatically detects the user's country using multiple strategies:

  1. IP-based detection (primary) - Uses free IP geolocation APIs
  2. Device locale (fallback) - Uses the device's locale settings
  3. Smart caching - Caches the detected country for 24 hours

Disable Auto-Detection #

PhoneInputField(
  autoDetect: false,
  initialCountry: CountryData.benin,
)

Custom Cache Duration #

PhoneInputField(
  detectionCacheDuration: 48, // Cache for 48 hours
)

βœ… Validation #

Built-in Validation #

Each country has specific validation rules:

final phone = PhoneNumber(
  country: CountryData.benin,
  nationalNumber: '0166640219',
);

print(phone.isValid); // true - valid Benin number
print(phone.formatted); // "01 66 64 02 19"
print(phone.international); // "+2290166640219"

Custom Validator #

Add your own validation logic:

PhoneInputField(
  validator: (phone) {
    if (phone == null || phone.isEmpty) {
      return 'Required';
    }
    
    // Custom rule: Only mobile numbers
    if (phone.country.code == 'FR' && 
        !phone.nationalNumber.startsWith('6') &&
        !phone.nationalNumber.startsWith('7')) {
      return 'Only mobile numbers allowed';
    }
    
    if (!phone.isValid) {
      return 'Invalid number';
    }
    
    return null;
  },
)

🎨 Customization #

Country Button Style #

Customize the country selector button:

PhoneInputField(
  countryButtonStyle: const CountryButtonStyle(
    showDialCode: false, // Hide dial code
    padding: EdgeInsets.all(8),
    flagStyle: TextStyle(fontSize: 32), // Bigger flag
  ),
)

Country Selector Type #

Choose between BottomSheet, Dialog, or Page:

PhoneInputField(
  countrySelectorConfig: const CountrySelectorConfig(
    type: CountrySelectorType.dialog, // or .bottomSheet, .page
    title: 'Choose Country',
    searchHint: 'Search...',
    locale: 'fr', // Show country names in French
  ),
)

Disable Auto-Formatting #

Show raw numbers without spaces:

PhoneInputField(
  autoFormat: false,
)

Custom Decoration #

Full control over the TextField appearance:

PhoneInputField(
  decoration: InputDecoration(
    labelText: 'Mobile',
    hintText: 'Enter your number',
    prefixIcon: const Icon(Icons.phone),
    border: OutlineInputBorder(
      borderRadius: BorderRadius.circular(12),
    ),
    filled: true,
    fillColor: Colors.grey[100],
  ),
)

πŸ“š Available Countries #

Quick Access #

// Individual countries
CountryData.benin
CountryData.gabon
CountryData.senegal
CountryData.coteDivoire
CountryData.cameroon
CountryData.france
CountryData.usa
// ... and more

// Lists
CountryData.allCountries // All available countries
CountryData.africanCountries // All African countries
CountryData.africanPlusMajor // African + France + USA

Search Countries #

// Search by name (English)
final results = CountryData.search('Benin');

// Search by name (French)
final results = CountryData.search('BΓ©nin', locale: 'fr');

// Get country by code
final benin = CountryData.getByCode('BJ');

// Get country by dial code
final benin = CountryData.getByDialCode('+229');

πŸ”§ API Reference #

PhoneInputField #

Parameter Type Default Description
controller PhoneController? null Optional controller for programmatic control
initialCountry Country? null Initial country (ignored if controller provided)
countries List<Country> All countries List of available countries
autoDetect bool true Auto-detect user's country
autoFormat bool true Format number as user types
validator Function? null Custom validation function
onChanged Function? null Callback when number changes
onCountryChanged Function? null Callback when country changes
decoration InputDecoration? null TextField decoration
enabled bool true Enable/disable the field
readOnly bool false Make field read-only

PhoneController #

Method Description
changeCountry(Country) Change the selected country
updateNumber(String) Update the phone number
clear() Clear the number (keep country)
reset(Country) Reset with new country
Getter Type Description
country Country Current country
nationalNumber String National number (no dial code)
international String Full international number
formatted String Formatted number
isValid bool Is number valid?

PhoneNumber #

Property Type Description
country Country The country
nationalNumber String National number
international String International format
formatted String Formatted display
isValid bool Validation status

🀝 Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

Adding More Countries #

To add support for additional countries, edit lib/src/core/data/countries_*.dart files.

πŸ“„ License #

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

πŸ’¬ Support #

For issues, questions, or feature requests, please open an issue.


Made with ❀️ in Benin πŸ‡§πŸ‡―

1
likes
0
points
233
downloads

Publisher

unverified uploader

Weekly Downloads

A customizable phone input field with auto country detection, formatting and validation. Perfect for African and international phone numbers.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, http, shared_preferences

More

Packages that depend on phone_input_plus