Flutter密码输入插件pin_code_text_field的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter密码输入插件pin_code_text_field的使用

pin_code_text_field 是一个美观且高度可定制的Flutter小部件,用于输入PIN码。它适用于登录和一次性密码(OTP)等场景。

使用方法

作为库使用该包

  1. 依赖于它

    pubspec.yaml 文件中添加:

    dependencies:
      pin_code_text_field: <VERSION>
    
  2. 安装它

    您可以通过命令行安装软件包:

    $ flutter packages get
    

    或者,您的编辑器可能支持 flutter packages get。请查阅编辑器文档以了解更多。

  3. 导入它

    现在可以在Dart代码中使用:

    import 'package:pin_code_text_field/pin_code_text_field.dart';
    

API

以下是 PinCodeTextField 的一些主要参数:

名称 类型 默认值 描述
isCupertino bool false 应用程序是否包装在 CupertinoApp 而不是 MaterialApp
maxLength int 4 PIN码的总长度和PIN框的数量
hideCharacter bool false 显示或隐藏PIN码
highlight bool false 高亮聚焦的PIN框
highlightAnimation bool false 动画高亮聚焦的PIN框
highlightAnimationBeginColor Color Colors.black 动画高亮的起始颜色
highlightAnimationEndColor Color Colors.white 动画高亮的结束颜色
highlightAnimationDuration Duration 500ms 高亮动画的持续时间
highlightColor Color Colors.black 设置聚焦PIN框的颜色
pinBoxDecoration BoxDecoration ProvidedPinBoxDecoration.defaultPinBoxDecoration 自定义单个PIN框。检查 ProvidedPinBoxDecoration 获取可用选项
pinTextStyle TextStyle PIN字符的文本样式
maskCharacter String “\u25CF” 遮罩PIN码的特殊字符。仅当 hideCharacter 设置为 true 时有效
pinBoxHeight double 70.0 PIN框的高度
pinBoxWidth double 70.0 PIN框的宽度
onDone void Function(String) 当达到PIN码的最大长度时的回调
hasTextBorderColor Color Colors.black 设置包含文本的PIN框的颜色
pinTextAnimatedSwitcherTransition Function(Widget child, Animation<…>) 文本出现/消失的动画。可以编写自己的动画或使用预设:PinCodeTextField.awesomeTransitionPinCodeTextField.defaultScalingTransitionPinCodeTextField.defaultRotateTransition
pinTextAnimatedSwitcherDuration Duration const Duration() pinTextAnimatedSwitcherTransition 的持续时间。检查 ProvidedPinBoxTextAnimation 获取可用选项
errorBorderColor Color Colors.red 如果 hasError 设置为 true,则将所有文本框高亮为此颜色
onTextChange Function(String) 输入文本变化时的回调
hasError bool false 将所有边框颜色设置为 errorBorderColor
autofocus bool false 视图进入时自动获取焦点
wrapAlignment WrapAlignment WrapAlignment.start 包裹PIN框的对齐方式
textDirection TextDirection TextDirection.ltr PIN码的方向
keyboardType TextInputType TextInputType.number 输入键盘类型
pinBoxColor Color null PIN框的颜色(会被自定义的 PinBoxDecoration 覆盖)
pinBoxBorderWidth double 2 PIN框的边框宽度
pinBoxRadius double 0 PIN框的圆角半径
hideDefaultKeyboard boolean false 是否隐藏默认键盘
highlightPinBoxColor Color false PIN框的背景颜色
hasUnderline bool false 为单个PIN框添加下划线

示例

下面是一个完整的示例demo,展示了如何使用 PinCodeTextField

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pin_code_text_field/pin_code_text_field.dart';

void main() => runApp(new SampleApp());

class SampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MainApp(),
    );
  }
}

class MainApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Pin Code TextField Example")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            MaterialButton(
              child: Text("Open Pin Code Input"),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => MyApp(isMaterial: true)),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

class MyApp extends StatefulWidget {
  final bool isMaterial;

  const MyApp({Key? key, required this.isMaterial}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  TextEditingController controller = TextEditingController(text: "");
  String thisText = "";
  int pinLength = 4;
  bool hasError = false;
  String errorMessage = "";

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

  @override
  Widget build(BuildContext context) {
    return widget.isMaterial
        ? materialPin()
        : cupertinoPin();
  }

  Scaffold materialPin() {
    return Scaffold(
      appBar: AppBar(
        title: Text("Material Pin Code Text Field Example"),
      ),
      body: Container(
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Padding(
                padding: const EdgeInsets.only(bottom: 60.0),
                child: Text(thisText, style: Theme.of(context).textTheme.titleMedium),
              ),
              Container(
                height: 100.0,
                child: GestureDetector(
                  onLongPress: () {
                    showDialog(
                      context: context,
                      builder: (context) {
                        return AlertDialog(
                          content: Text("Paste clipboard stuff into the pinbox?"),
                          actions: [
                            TextButton(
                              onPressed: () async {
                                var copiedText = await Clipboard.getData("text/plain");
                                if (copiedText?.text.isNotEmpty == true) {
                                  controller.text = copiedText.text;
                                }
                                Navigator.of(context).pop();
                              },
                              child: Text("YES"),
                            ),
                            TextButton(
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                              child: Text("No"),
                            )
                          ],
                        );
                      },
                    );
                  },
                  child: PinCodeTextField(
                    autofocus: true,
                    controller: controller,
                    hideCharacter: true,
                    highlight: true,
                    highlightColor: Colors.blue,
                    defaultBorderColor: Colors.black,
                    hasTextBorderColor: Colors.green,
                    highlightPinBoxColor: Colors.orange,
                    maxLength: pinLength,
                    hasError: hasError,
                    maskCharacter: "😎",
                    onTextChanged: (text) {
                      setState(() {
                        hasError = false;
                      });
                    },
                    onDone: (text) {
                      print("DONE $text");
                      print("DONE CONTROLLER ${controller.text}");
                    },
                    pinBoxWidth: 50,
                    pinBoxHeight: 64,
                    hasUnderline: true,
                    wrapAlignment: WrapAlignment.spaceAround,
                    pinBoxDecoration: ProvidedPinBoxDecoration.defaultPinBoxDecoration,
                    pinTextStyle: TextStyle(fontSize: 22.0),
                    pinTextAnimatedSwitcherTransition: ProvidedPinBoxTextAnimation.scalingTransition,
                    pinTextAnimatedSwitcherDuration: Duration(milliseconds: 300),
                    highlightAnimationBeginColor: Colors.black,
                    highlightAnimationEndColor: Colors.white12,
                    keyboardType: TextInputType.number,
                  ),
                ),
              ),
              Visibility(
                child: Text(
                  "Wrong PIN!",
                ),
                visible: hasError,
              ),
              Padding(
                padding: const EdgeInsets.only(top: 32.0),
                child: Wrap(
                  alignment: WrapAlignment.spaceEvenly,
                  children: [
                    MaterialButton(
                      color: Colors.blue,
                      textColor: Colors.white,
                      child: Text("+"),
                      onPressed: () {
                        setState(() {
                          this.pinLength++;
                        });
                      },
                    ),
                    MaterialButton(
                      color: Colors.blue,
                      textColor: Colors.white,
                      child: Text("-"),
                      onPressed: () {
                        setState(() {
                          this.pinLength--;
                        });
                      },
                    ),
                    MaterialButton(
                      color: Colors.blue,
                      textColor: Colors.white,
                      child: Text("SUBMIT"),
                      onPressed: () {
                        setState(() {
                          this.thisText = controller.text;
                        });
                      },
                    ),
                    MaterialButton(
                      color: Colors.red,
                      textColor: Colors.white,
                      child: Text("SUBMIT Error"),
                      onPressed: () {
                        setState(() {
                          this.hasError = true;
                        });
                      },
                    ),
                    MaterialButton(
                      color: Colors.pink,
                      textColor: Colors.white,
                      child: Text("CLEAR PIN"),
                      onPressed: () {
                        controller.clear();
                      },
                    ),
                    MaterialButton(
                      color: Colors.lime,
                      textColor: Colors.black,
                      child: Text("SET TO 456"),
                      onPressed: () {
                        controller.text = "456";
                      },
                    ),
                  ],
                ),
              )
            ],
          ),
        ),
      ),
    );
  }

  CupertinoPageScaffold cupertinoPin() {
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text("Cupertino Pin Code Text Field Example"),
      ),
      child: SafeArea(
        child: Container(
          child: SingleChildScrollView(
            child: Container(
              color: Colors.blue,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Padding(
                    padding: const EdgeInsets.only(bottom: 60.0),
                    child: Text(thisText),
                  ),
                  PinCodeTextField(
                    autofocus: false,
                    controller: controller,
                    hideCharacter: true,
                    highlight: true,
                    highlightColor: CupertinoColors.activeBlue,
                    defaultBorderColor: CupertinoColors.black,
                    hasTextBorderColor: CupertinoColors.activeGreen,
                    maxLength: pinLength,
                    hasError: hasError,
                    maskCharacter: "🐶",
                    onTextChanged: (text) {
                      setState(() {
                        hasError = false;
                        thisText = text;
                      });
                    },
                    isCupertino: true,
                    onDone: (text) {
                      print("DONE $text");
                    },
                    wrapAlignment: WrapAlignment.end,
                    pinBoxDecoration: ProvidedPinBoxDecoration.roundedPinBoxDecoration,
                    pinTextStyle: TextStyle(fontSize: 30.0),
                    pinTextAnimatedSwitcherTransition: ProvidedPinBoxTextAnimation.scalingTransition,
                    pinTextAnimatedSwitcherDuration: Duration(milliseconds: 300),
                    highlightAnimation: true,
                    highlightAnimationBeginColor: Colors.black,
                    highlightAnimationEndColor: Colors.white12,
                  ),
                  Visibility(
                    child: Text(
                      "Wrong PIN!",
                      style: TextStyle(color: CupertinoColors.destructiveRed),
                    ),
                    visible: hasError,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 32.0),
                    child: Wrap(
                      alignment: WrapAlignment.spaceEvenly,
                      children: [
                        CupertinoButton(
                          child: Text("+"),
                          onPressed: () {
                            setState(() {
                              this.pinLength++;
                            });
                          },
                        ),
                        CupertinoButton(
                          child: Text("-"),
                          onPressed: () {
                            setState(() {
                              this.pinLength--;
                            });
                          },
                        ),
                        CupertinoButton(
                          child: Text("SUBMIT"),
                          onPressed: () {
                            setState(() {
                              this.thisText = controller.text;
                            });
                          },
                        ),
                        CupertinoButton(
                          child: Text("SUBMIT Error"),
                          onPressed: () {
                            setState(() {
                              this.hasError = true;
                            });
                          },
                        )
                      ],
                    ),
                  )
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

这个示例展示了如何创建一个带有PIN码输入框的应用程序,并提供了Material和Cupertino两种风格的界面选择。您可以根据需要调整和扩展此示例。


更多关于Flutter密码输入插件pin_code_text_field的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter密码输入插件pin_code_text_field的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用pin_code_text_field插件的示例代码。这个插件通常用于输入PIN码或密码,提供了一些便利的功能,比如自动聚焦下一个输入框、隐藏和显示密码等。

首先,确保在你的pubspec.yaml文件中添加pin_code_text_field依赖:

dependencies:
  flutter:
    sdk: flutter
  pin_code_text_field: ^2.0.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

接下来,是一个简单的示例代码,展示如何使用PinCodeTextField

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Pin Code TextField Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: PinCodeScreen(),
    );
  }
}

class PinCodeScreen extends StatefulWidget {
  @override
  _PinCodeScreenState createState() => _PinCodeScreenState();
}

class _PinCodeScreenState extends State<PinCodeScreen> {
  final _controller = TextEditingController();
  final _focusNode = FocusNode();

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

  void _onSubmit(String pin) {
    // 在这里处理提交的PIN码
    print('Submitted PIN: $pin');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Pin Code Input Demo'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: PinCodeTextField(
            controller: _controller,
            length: 6,  // PIN码长度
            obscureText: false,  // 是否隐藏文本
            animationType: AnimationType.fade,
            width: 50.0,
            height: 60.0,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(8),
              boxShadow: [
                BoxShadow(
                  color: Colors.grey.withOpacity(0.5),
                  spreadRadius: 5,
                  blurRadius: 7,
                  offset: Offset(0, 3), // changes position of shadow
                ),
              ],
            ),
            borderActiveColor: Colors.blue,
            onCompleted: _onSubmit,
            onChanged: (value) {
              // 实时处理PIN码输入变化
              print('Current PIN: $value');
            },
            pinTheme: PinTheme(
              shape: PinCodeFieldShape.box,
              borderRadius: BorderRadius.circular(8),
              fieldSize: 50.0,
              activeColor: Colors.blue,
              inactiveColor: Colors.grey[300]!,
              inactiveFillColor: Colors.white,
              selectedColor: Colors.blueAccent,
              disabledColor: Colors.grey[400]!,
              animationDuration: Duration(milliseconds: 300),
            ),
            keyboardType: TextInputType.number,
            textStyle: TextStyle(
              fontSize: 20.0,
            ),
            animationDuration: Duration(milliseconds: 300),
          ),
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个包含PinCodeTextField的简单Flutter应用。以下是关键点的总结:

  1. PinCodeTextField: 用于输入PIN码的主要组件。
  2. controller: TextEditingController用于控制文本字段。
  3. length: 定义PIN码的长度。
  4. obscureText: 是否隐藏输入的文本。
  5. onCompleted: 当用户完成输入时触发的回调。
  6. onChanged: 当用户输入变化时触发的回调。
  7. pinTheme: 用于自定义PIN码输入框的外观。

你可以根据需要调整这些参数来满足你的具体需求。

回到顶部