ip_address_input 0.0.2 copy "ip_address_input: ^0.0.2" to clipboard
ip_address_input: ^0.0.2 copied to clipboard

A Flutter widget for entering IPv4 addresses with 4 segmented fields, auto-advance, paste support, form validation, and full visual customization.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:ip_address_input/ip_address_input.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ip_address_input demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      home: const IpAddressInputDemo(),
    );
  }
}

class IpAddressInputDemo extends StatefulWidget {
  const IpAddressInputDemo({super.key});

  @override
  State<IpAddressInputDemo> createState() => _IpAddressInputDemoState();
}

class _IpAddressInputDemoState extends State<IpAddressInputDemo> {
  String _value = '';
  String _completed = '';
  final _controller = IpAddressInputController();
  final _formKey = GlobalKey<FormState>();

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Demo — IP Address Input')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // ─── onChanged + onCompleted ──────────────────────────────────
            _Section(
              title: 'onChanged + onCompleted',
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  IpAddressInput(
                    label: 'IP Address',
                    onChanged: (v) => setState(() => _value = v),
                    onCompleted: (v) => setState(() => _completed = v),
                  ),
                  const SizedBox(height: 8),
                  Text('onChanged: $_value'),
                  if (_completed.isNotEmpty)
                    Text(
                      'onCompleted: $_completed',
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                ],
              ),
            ),
            const SizedBox(height: 32),

            // ─── IpAddressInputController ──────────────────────────────────
            _Section(
              title: 'IpAddressInputController',
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  IpAddressInput(
                    label: 'With controller',
                    controller: _controller,
                  ),
                  const SizedBox(height: 12),
                  Row(
                    children: [
                      FilledButton(
                        onPressed: () => _controller.setValue('10.0.0.1'),
                        child: const Text('Set 10.0.0.1'),
                      ),
                      const SizedBox(width: 8),
                      OutlinedButton(
                        onPressed: _controller.clear,
                        child: const Text('Clear'),
                      ),
                    ],
                  ),
                ],
              ),
            ),
            const SizedBox(height: 32),

            // ─── Paste ────────────────────────────────────────────────────
            _Section(
              title: 'Auto paste',
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const IpAddressInput(label: 'Paste an IP here (e.g. 192.168.1.1)'),
                  const SizedBox(height: 4),
                  Text(
                    'Paste a full IP in the first field — it distributes automatically.',
                    style: Theme.of(context).textTheme.bodySmall,
                  ),
                ],
              ),
            ),
            const SizedBox(height: 32),

            // ─── separatorWidget ──────────────────────────────────────────
            _Section(
              title: 'Custom separatorWidget',
              child: IpAddressInput(
                label: 'With icon separator',
                separatorWidget: const Padding(
                  padding: EdgeInsets.symmetric(horizontal: 4),
                  child: Icon(Icons.fiber_manual_record, size: 6),
                ),
              ),
            ),
            const SizedBox(height: 32),

            // ─── IpAddressFormField ───────────────────────────────────────
            _Section(
              title: 'IpAddressFormField (validator)',
              child: Form(
                key: _formKey,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    IpAddressFormField(
                      label: 'Router IP',
                      autovalidateMode: AutovalidateMode.onUserInteraction,
                      validator: (v) {
                        if (v == null || v.replaceAll('.', '').isEmpty) {
                          return 'Please fill in the IP address.';
                        }
                        final parts = v.split('.');
                        if (parts.length != 4 || parts.any((p) => p.isEmpty)) {
                          return 'Incomplete IP address.';
                        }
                        for (final p in parts) {
                          final n = int.tryParse(p);
                          if (n == null || n < 0 || n > 255) {
                            return 'Invalid octet: $p (must be 0–255).';
                          }
                        }
                        return null;
                      },
                    ),
                    const SizedBox(height: 12),
                    FilledButton(
                      onPressed: () => _formKey.currentState?.validate(),
                      child: const Text('Validate'),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 32),

            // ─── Disabled ─────────────────────────────────────────────────
            const _Section(
              title: 'Disabled',
              child: IpAddressInput(
                label: 'Read only',
                initialValue: '8.8.8.8',
                enabled: false,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _Section extends StatelessWidget {
  const _Section({required this.title, required this.child});
  final String title;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(title, style: Theme.of(context).textTheme.titleMedium),
        const SizedBox(height: 12),
        child,
      ],
    );
  }
}
1
likes
160
points
--
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter widget for entering IPv4 addresses with 4 segmented fields, auto-advance, paste support, form validation, and full visual customization.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on ip_address_input