flutter_smart_otp 1.0.0 copy "flutter_smart_otp: ^1.0.0" to clipboard
flutter_smart_otp: ^1.0.0 copied to clipboard

A highly customizable, production-ready OTP / PIN input field for Flutter with auto-focus, paste support, validation, RTL/LTR support, and rich styling options.

flutter_smart_otp #

pub package License: MIT

A highly customizable, production-ready OTP / PIN input field for Flutter. SmartOtpField renders a row of individual input boxes that behave like a single logical text field — with auto-focus, backspace navigation, full paste support, validation, and rich styling — while remaining fully accessible and leak-free.

Auto-advance • Auto-back on backspace • Paste anywhere • Obscure text • Validation • RTL/LTR • Fully custom styling

Features #

  • ✅ Custom OTP length (any number of boxes)
  • ✅ Auto-focus to the next field as the user types
  • ✅ Auto-focus to the previous field on backspace
  • ✅ Paste a complete code into any box — it is distributed across all boxes
  • ✅ Built-in validation with validator and AutovalidateMode
  • ✅ Obscure text support (PIN-style entry) with a custom obscuring character
  • ✅ Enable / disable state
  • ✅ Read-only mode
  • ✅ Keyboard type customization
  • TextInputFormatter support
  • ✅ Full cursor customization (color, width, height, radius, visibility)
  • ✅ Custom text style
  • ✅ Custom border, border color, focused border color, error border color, disabled border color, border width, and border radius
  • ✅ Advanced borderBuilder / decorationBuilder hooks for total visual control (gradients, shadows, custom shapes)
  • ✅ Box width, height, and spacing customization
  • ✅ Autofocus
  • ✅ Custom FocusNode list support
  • ✅ Custom TextEditingController list support
  • ✅ Right-to-left (RTL) and left-to-right (LTR) layout support
  • ✅ Responsive layout
  • ✅ Leak-free state management with correct disposal of internally-created resources only
  • ✅ Accessibility support via Semantics
  • onChanged, onCompleted, and onFocusChanged callbacks
  • ✅ Imperative control (clear, validate, setError) via GlobalKey

Installation #

Add the package to your pubspec.yaml:

dependencies:
  flutter_smart_otp: ^1.0.0

Then run:

flutter pub get

Basic usage #

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SmartOtpField(
          length: 6,
          onChanged: (value) => debugPrint('Value: $value'),
          onCompleted: (value) => debugPrint('Completed: $value'),
        ),
      ),
    );
  }
}

Styling #

SmartOtpField(
  length: 5,
  boxWidth: 52,
  boxHeight: 60,
  spacing: 10,
  borderRadius: 16,
  borderWidth: 2,
  borderColor: const Color(0xFFE0E0E0),
  focusedBorderColor: const Color(0xFF7C4DFF),
  errorBorderColor: const Color(0xFFFF5252),
  fillColor: const Color(0xFFF3F1FF),
  textStyle: const TextStyle(fontSize: 22, fontWeight: FontWeight.w700),
  cursorColor: const Color(0xFF7C4DFF),
)

Obscured PIN entry #

SmartOtpField(
  length: 6,
  obscureText: true,
  obscuringCharacter: '●',
)

Validation #

final fieldKey = GlobalKey<SmartOtpFieldState>();

SmartOtpField(
  key: fieldKey,
  length: 4,
  validator: (value) =>
      (value != null && value.length == 4) ? null : 'Enter all 4 digits',
  autovalidateMode: AutovalidateMode.onUserInteraction,
);

// Trigger validation manually, e.g. from a "Verify" button:
final isValid = fieldKey.currentState!.validate();

// Or surface a server-side error after an async check:
fieldKey.currentState!.setError('Incorrect code, please try again.');

Using your own controllers and focus nodes #

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

SmartOtpField(
  length: 4,
  controllers: controllers,
  focusNodes: focusNodes,
);

// You remain responsible for disposing controllers/focusNodes you created.

Right-to-left layout #

SmartOtpField(
  length: 4,
  textDirection: TextDirection.rtl,
)

Imperative API #

Attach a GlobalKey<SmartOtpFieldState> to control the field from outside:

Method Description
clear() Clears every box and refocuses the first box.
validate() Runs validator against the current value, returns bool.
setError(String?) Manually sets or clears the displayed error message.
value Getter returning the current combined OTP string.

Callbacks #

Callback Signature When it fires
onChanged void Function(String value) On every keystroke, paste, or deletion.
onCompleted void Function(String value) Whenever all boxes become filled.
onFocusChanged void Function(int index, bool hasFocus) Whenever an individual box gains/loses focus.

Example app #

See the example/ directory for a complete demo covering: basic verification, custom styling, obscured PIN entry, validation with simulated server errors, a resend-code timer using external controllers, enabled/disabled/read-only toggling, and RTL layout.

Additional information #

Contributions, bug reports, and feature requests are welcome via the issue tracker. This package has no third-party runtime dependencies beyond the Flutter SDK and characters (already a transitive Flutter dependency).

Licensed under the MIT License.

2
likes
160
points
36
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

A highly customizable, production-ready OTP / PIN input field for Flutter with auto-focus, paste support, validation, RTL/LTR support, and rich styling options.

Repository (GitHub)
View/report issues

Topics

#otp #pin #input #form #widget

License

MIT (license)

Dependencies

characters, flutter

More

Packages that depend on flutter_smart_otp