패키지, 저장소 및 앱 카테고리 검색

pinput 표지
패키지 상세v7.0.0

pinput

핀 코드 입력(OTP) 텍스트 필드, iOS SMS 자동 채우기, 안드로이드 SMS 자동 채우기 일회용 코드, 비밀번호, 패스코드, 캡차, 보안, 쿠폰, 와처, 2FA, 두 단계 인증

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
62.7만
좋아요
3.5천
Pub 점수
160

패키지 설치

flutter pub add pinput

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

Pinput은 깔끔하고 사용자 정의 가능한 PIN 코드, OTP, 비밀번호 및 패스코드 입력 필드를 생성하기 위한 Flutter 패키지입니다. 일회용 코드에 대해 iOS 및 Android SMS 자동 완성 기능을 지원하여 2단계 인증, 두 단계 검증 또는 쿠폰 입력 시 사용자 경험을 향상시킵니다. 깔끔한 UI와 직관적인 제스처로 설계되어 웹, macOS, Windows, Linux 등 모든 주요 플랫폼에서 작동합니다. 부드러운 전환, 검증 및 인증 프로세스에의 간편한 통합이 가능합니다.

사용 사례

  • 이중 인증
  • 쿠폰 또는 프로모 코드 입력
  • 보안 패스코드 입력
  • 캡차 검증
  • OTP 로그인 흐름
  • 비밀번호 복구

주요 기능

  • iOS 및 Android SMS 자동 완성 지원
  • 사용자 정의 가능한 디자인 및 스타일링
  • 크로스 플랫폼 호환성
  • 필드 간 자동 포커스
  • 내장 검증 유틸리티
  • 부드러운 애니메이션

적합한 대상

  • 인증 화면
  • 보안 로그인 인터페이스
  • 전자상거래 체크아웃 양식
  • 사용자 온보딩 흐름
  • 모바일 앱 보안 기능

고려 사항

  • OTP 제출 로직을 수동으로 처리해야 합니다
  • 제한된 내장 오류 피드백
  • 복잡한 워크플로우를 위해 추가 상태 관리가 필요할 수 있습니다
  • 매우 긴 입력 시퀀스에 최적화되지 않음
  • 내장된 생체 인식 통합 없음

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

Flutter pin code input

Need anything Flutter related? Reach out on LinkedIn

Pub package Github starts style: effective dart pub package

Flutter Pinput is a package that provides an easy-to-use and customizable Pin code input field. It offers several features such as animated decoration switching, form validation, SMS autofill, custom cursor, copying from clipboard, and more. It also provides beautiful examples that you can choose from.

Features:

  • Animated Decoration Switching
  • Form validation
  • SMS Autofill on iOS
  • SMS Autofill on Android
  • Standard Cursor
  • Custom Cursor
  • Cursor Animation
  • Copy From Clipboard
  • Ready For Custom Keyboard
  • Standard Paste option
  • Obscuring Character
  • Obscuring Widget
  • Haptic Feedback
  • Close Keyboard After Completion
  • Beautiful Examples

Support

PRs Welcome

Discord Channel

Examples app on Github has multiple templates to choose from

Don't forget to give it a star ⭐

Demo

Live Demo Rounded With Shadows Rounded With Cursor
Rounded Filled With Bottom Cursor Filled

Getting Started

The pin has 6 states default focused, submitted, following, disabled, error, you can customize each state by specifying theme parameter. Pin smoothly animates from one state to another automatically. PinTheme Class

Property Default/Type
width 56.0
height 60.0
textStyle TextStyle()
margin EdgeInsetsGeometry
padding EdgeInsetsGeometry
constraints BoxConstraints

You can use standard Pinput like so

Widget buildPinPut() {
  return Pinput(
    onCompleted: (pin) => print(pin),
  );
}

If you want to customize it, create defaultPinTheme first.

final defaultPinTheme = PinTheme(
  width: 56,
  height: 56,
  textStyle: TextStyle(fontSize: 20, color: Color.fromRGBO(30, 60, 87, 1), fontWeight: FontWeight.w600),
  decoration: BoxDecoration(
    border: Border.all(color: Color.fromRGBO(234, 239, 243, 1)),
    borderRadius: BorderRadius.circular(20),
  ),
);

if you want all pins to be the same don't pass other theme parameters, If not, create focusedPinTheme, submittedPinTheme, followingPinTheme, errorPinTheme from defaultPinTheme

final focusedPinTheme = defaultPinTheme.copyDecorationWith(
  border: Border.all(color: Color.fromRGBO(114, 178, 238, 1)),
  borderRadius: BorderRadius.circular(8),
);

final submittedPinTheme = defaultPinTheme.copyWith(
  decoration: defaultPinTheme.decoration.copyWith(
    color: Color.fromRGBO(234, 239, 243, 1),
  ),
);

Put everything together

final defaultPinTheme = PinTheme(
  width: 56,
  height: 56,
  textStyle: TextStyle(fontSize: 20, color: Color.fromRGBO(30, 60, 87, 1), fontWeight: FontWeight.w600),
  decoration: BoxDecoration(
    border: Border.all(color: Color.fromRGBO(234, 239, 243, 1)),
    borderRadius: BorderRadius.circular(20),
  ),
);

final focusedPinTheme = defaultPinTheme.copyDecorationWith(
  border: Border.all(color: Color.fromRGBO(114, 178, 238, 1)),
  borderRadius: BorderRadius.circular(8),
);

final submittedPinTheme = defaultPinTheme.copyWith(
  decoration: defaultPinTheme.decoration.copyWith(
    color: Color.fromRGBO(234, 239, 243, 1),
  ),
);

return Pinput(
defaultPinTheme: defaultPinTheme,
focusedPinTheme: focusedPinTheme,
submittedPinTheme: submittedPinTheme,
validator: (s) {
return s == '2222' ? null : 'Pin is incorrect';
},
pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,
showCursor: true,
onCompleted: (pin) => print(pin),
);

SMS Autofill

iOS

Works out of the box, by tapping the code on top of the keyboard

Android

If you are using firebase_auth you have to set controller's value in verificationCompleted callback, here is an example code:

    Pinput(
      controller: pinController,
    );

And set pinController's value in verificationCompleted callback:

    await FirebaseAuth.instance.verifyPhoneNumber(
      verificationCompleted: (PhoneAuthCredential credential) {
        pinController.setText(credential.smsCode);
      },
      verificationFailed: (FirebaseAuthException e) {},
      codeSent: (String verificationId, int? resendToken) {},
      codeAutoRetrievalTimeout: (String verificationId) {},
    );

If you aren't using firebase_auth, you have two options, SMS Retriever API and SMS User Consent API,

SmartAuth is a wrapper package for Flutter for these APIs, so go ahead and add it as a dependency.

SMS Retriever API

To use Retriever API you need the App signature - guide

Note that The App Signature might be different for debug and release mode

Once you get the app signature, you should include it in the SMS message in you backend like so:

SMS example:

Your ExampleApp code is: 123456
kg+TZ3A5qzS

Example Code

Sms code will be automatically applied, without user interaction.

SMS User Consent API

You don't need the App signature, the user will be prompted to confirm reading the message Example Code

Request Hint

See Example app for more templates

Tips

  • Controller
/// Create Controller  
final pinController = TextEditingController();

/// Set text programmatically  
pinController.setText('1222');

/// Append typed character, useful if you are using custom keyboard  
pinController.append('1', 4);

/// Delete last character  
pinController.delete();

/// Don't call setText, append, delete in build method, this is just illustration.  

return Pinput(
  controller: pinController,  
);  
  • Focus
/// Create FocusNode  
final pinputFocusNode = FocusNode();

/// Focus pinput  
pinputFocusNode.requestFocus();

/// UnFocus pinput  
pinputFocusNode.unfocus();

/// Don't call requestFocus, unfocus in build method, this is just illustration.  

return Pinput(
  focusNode: pinputFocusNode,
);  
  • Validation
/// Create key
final formKey = GlobalKey<FormState>();

/// Validate manually
/// Don't call validate in build method, this is just illustration.
formKey.currentState!.validate();

return Form(
  key: formKey,
  child: Pinput(
  // Without Validator
  // If true error state will be applied no matter what validator returns
  forceErrorState: true,
  // Text will be displayed under the Pinput
  errorText: 'Error',

  /// ------------
  /// With Validator
  /// Auto validate after user tap on keyboard done button, or completes Pinput
  pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,
  validator: (pin) {
    if (pin == '2224') return null;

    /// Text will be displayed under the Pinput
    return 'Pin is incorrect';
    },
  ),
);

FAQ

autofill isn't working on iOS?
  • Make sure you are using real device, not simulator
  • Temporary replace Pinput with TextField, and check if autofill works. If, not it's probably a problem with SMS you are getting, autofill doesn't work with most of the languages
  • If you are using non stable version of Flutter that might be cause because something might be broken inside the Framework
are you using firebase_auth?

You should set controller's value in verificationCompleted callback, here is an example code:

    Pinput(
      controller: pinController,
    );
    
    await FirebaseAuth.instance.verifyPhoneNumber(
      verificationCompleted: (PhoneAuthCredential credential) {
        pinController.setText(credential.smsCode);
      },
      verificationFailed: (FirebaseAuthException e) {},
      codeSent: (String verificationId, int? resendToken) {},
      codeAutoRetrievalTimeout: (String verificationId) {},
    );

카테고리

의존성

의존성 목록 2 개

소스 저장소

이 패키지를 사용하는 프로젝트

순위