flutter_otp_widget 1.0.1 copy "flutter_otp_widget: ^1.0.1" to clipboard
flutter_otp_widget: ^1.0.1 copied to clipboard

A highly customizable OTP (One-Time Password) text field widget for Flutter with support for multiple styles, themes, and input types.

Flutter OTP Widget #

A highly customizable OTP (One-Time Password) text field widget for Flutter with support for multiple styles, themes, and input types.

Features #

Multiple Field Styles

  • Box (default) - Traditional bordered boxes
  • Underline - Minimalist underlined fields
  • Circle - Circular PIN-style fields

🎨 Flexible Theming

  • Light and dark theme presets
  • Fully customizable colors and dimensions
  • Automatic theme adaptation

⌨️ Input Type Control

  • Numbers only (default)
  • Text only (letters)
  • Alphanumeric (mixed)

🔒 Secure Input

  • Password/PIN mode with obscured text
  • Customizable obscuring character

🎯 State Management

  • Error state styling
  • Disabled state
  • Auto-focus support
  • Focus and change callbacks

Smart Navigation

  • Auto-advance to next field
  • Backspace to previous field
  • Arrow key navigation
  • Automatic completion detection

Screenshots #


Box Style

Underline Style

Circle Style

Secure PIN Entry

Error State

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  flutter_otp_widget: ^1.0.1

Then run:

flutter pub get

Basic Usage #

import 'package:flutter_otp_widget/flutter_otp_widget.dart';

class OTPScreen extends StatefulWidget {
  @override
  _OTPScreenState createState() => _OTPScreenState();
}

class _OTPScreenState extends State<OTPScreen> {
  final controllers = List.generate(6, (_) => TextEditingController());
  final focusNodes = List.generate(6, (_) => FocusNode());

  @override
  void dispose() {
    for (var controller in controllers) {
      controller.dispose();
    }
    for (var node in focusNodes) {
      node.dispose();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: OTPTextField(
          controllers: controllers,
          focusNodes: focusNodes,
          textStyle: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
          onCompleted: (otp) {
            print('OTP Entered: $otp');
            // Verify OTP
          },
          onChange: (value) {
            print('Current OTP: $value');
          },
        ),
      ),
    );
  }
}

Examples #

Different Styles #

// Box Style (Default)
OTPTextField(
  controllers: controllers,
  focusNodes: focusNodes,
  fieldStyle: OTPFieldStyle.box,
  textStyle: TextStyle(fontSize: 24),
)

// Underline Style
OTPTextField(
  controllers: controllers,
  focusNodes: focusNodes,
  fieldStyle: OTPFieldStyle.underline,
  textStyle: TextStyle(fontSize: 24),
)

// Circle Style
OTPTextField(
  controllers: controllers,
  focusNodes: focusNodes,
  fieldStyle: OTPFieldStyle.circle,
  textStyle: TextStyle(fontSize: 24),
)

Custom Theme #

OTPTextField(
  controllers: controllers,
  focusNodes: focusNodes,
  theme: OTPTheme.custom(
    borderColor: Colors.grey,
    focusedBorderColor: Colors.blue,
    errorBorderColor: Colors.red,
    fillColor: Colors.white,
    borderRadius: BorderRadius.circular(12),
  ),
  textStyle: TextStyle(fontSize: 24),
)

Text Input #

OTPTextField(
  controllers: controllers,
  focusNodes: focusNodes,
  inputType: OTPInputType.text,
  textCapitalization: TextCapitalization.characters,
  textStyle: TextStyle(fontSize: 24),
)

Secure PIN Entry #

OTPTextField(
  controllers: controllers,
  focusNodes: focusNodes,
  fieldStyle: OTPFieldStyle.circle,
  obscureText: true,
  obscuringCharacter: '●',
  textStyle: TextStyle(fontSize: 24),
)

Error State #

OTPTextField(
  controllers: controllers,
  focusNodes: focusNodes,
  hasError: isWrongOTP,
  theme: OTPTheme.light().copyWith(
    errorBorderColor: Colors.red,
  ),
  textStyle: TextStyle(fontSize: 24),
)

4-Digit Code #

final controllers = List.generate(4, (_) => TextEditingController());
final focusNodes = List.generate(4, (_) => FocusNode());

OTPTextField(
  controllers: controllers,
  focusNodes: focusNodes,
  fieldStyle: OTPFieldStyle.underline,
  textStyle: TextStyle(fontSize: 24),
)

With Center Spacing (3-3 Layout) #

OTPTextField(
  controllers: controllers, // 6 controllers
  focusNodes: focusNodes,
  centerSpacing: 16, // Extra space in the middle
  textStyle: TextStyle(fontSize: 24),
)
// Layout: XXX   XXX

Parameters #

OTPTextField #

Parameter Type Default Description
controllers List<TextEditingController> required Text controllers for each field
focusNodes List<FocusNode> required Focus nodes for each field
textStyle TextStyle required Text style for input
onCompleted ValueChanged<String>? null Callback when all fields are filled
onChange ValueChanged<String>? null Callback when any field changes
fieldWidth double 40 Width of each field
fieldHeight double 50 Height of each field
fieldSpacing double 8 Spacing between fields
centerSpacing double? null Extra spacing at the middle
theme OTPTheme? null Theme configuration
fieldStyle OTPFieldStyle box Visual style of fields
inputType OTPInputType number Type of input allowed
obscureText bool false Whether to obscure text
obscuringCharacter String '●' Character for obscuring
enabled bool true Whether fields are enabled
autoFocus bool false Auto-focus first field
hasError bool false Show error state
textCapitalization TextCapitalization none Text capitalization mode

See the API documentation for complete parameter list.

State Management Integration #

The package works seamlessly with any state management solution. Here's an example with Riverpod:

@riverpod
class OtpControllers extends _$OtpControllers {
  @override
  List<TextEditingController> build(int count) {
    final controllers = List.generate(count, (_) => TextEditingController());

    ref.onDispose(() {
      for (var controller in controllers) {
        controller.dispose();
      }
    });

    return controllers;
  }

  void clear() {
    for (var controller in state) {
      controller.clear();
    }
  }
}

// Usage
final controllers = ref.watch(otpControllersProvider(6));

Contributing #

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

License #

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

Issues and Feedback #

Please file issues, bugs, or feature requests in our issue tracker.

Example App #

For a complete example with all features demonstrated, check out the example directory.

0
likes
160
points
83
downloads
screenshot

Publisher

unverified uploader

Weekly Downloads

A highly customizable OTP (One-Time Password) text field widget for Flutter with support for multiple styles, themes, and input types.

Repository (GitHub)
View/report issues

Topics

#otp #textfield #pin #verification #authentication

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flutter_otp_widget