[译]Flutter Pin 码(短信验证码)输入组件 pinput
本文正在参加「金石计划」
本文翻译自: pinput | Flutter Package (flutter-io.cn)
译时版本:2.2.31
Tornike 和 伟大的 贡献者们 带来的 Flutter Pinput
该 Flutter 包用于方便创建可定制的 Pin 码(短信验证码)输入组件,设计者甚至不需要在 Figma 中画出。
如果使用的 Flutter 版本低于 3.7.0 ,需要使用 Pinput 的 2.2.21 版本
友情提示: 🤫 告诉你的PM你需要一周的时间来实现该特性,然后就可以和朋友们去玩耍了。
特性
- 切换动画
- 表单验证
- iOS 平台的 SMS (短信)自动填充
- Android 平台的 SMS (短信)自动填充
- 标准光标
- 自定义光标
- 光标动画
- 从剪贴板复制
- 可用于自定义键盘
- 标准的粘贴选项
- 模糊字符
- 模糊组件
- 触觉反馈
- 完成后关闭键盘
- 美观的 示例
支持
欢迎 PR
讨论 频道
Github 上的示例 应用有多个模板可选。
别忘了给个 Star ⭐
演示
实况演示 | 圆角带阴影 | 圆角带光标 |
---|---|---|
![]() | ![]() | ![]() |
圆角填充 | 底部光标 | 填充 |
---|---|---|
![]() | ![]() | ![]() |
开始
Pin 有六个状态 default
、 focused
、 submitted
、 following
、 disabled
、 error
,可以指定主题参数自定义每个状态。 Pin 会自动地在状态间进行丝滑的动画。
PinTheme Class
属性 | 默认/类型 |
---|---|
width | 56.0 |
height | 60.0 |
textStyle | TextStyle() |
margin | EdgeInsetsGeometry |
padding | EdgeInsetsGeometry |
constraints | BoxConstraints |
可如下使用标准的 Pinput
Widget buildPinPut() {
return Pinput(
onCompleted: (pin) => print(pin),
);
}
如果想要自定义,首先创建 defaultPinTheme
。
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),
),
);
如果想要所有的 Pin 都是一样的,则不需要传递任何主题参数,否则需要从 defaultPinTheme
创建focusedPinTheme
、 submittedPinTheme
、 followingPinTheme
、 errorPinTheme
。
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),
),
);
把所有内容整合在一起:
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 (短信)自动填充
iOS
开箱即用,点一下键盘上方的 PIN 码
Android
如果是在使用 firebase_auth,需要把 androidSmsAutofillMethod
设置为 AndroidSmsAutofillMethod.none
,并在 verificationCompleted
的回调中设置 controller
的值。下面是示例代码:
Pinput(
androidSmsAutofillMethod: AndroidSmsAutofillMethod.none,
controller: pinController,
);
在 verificationCompleted
回调中设置 pinController 的值:
await FirebaseAuth.instance.verifyPhoneNumber(
verificationCompleted: (PhoneAuthCredential credential) {
pinController.setText(credential.smsCode);
},
verificationFailed: (FirebaseAuthException e) {},
codeSent: (String verificationId, int? resendToken) {},
codeAutoRetrievalTimeout: (String verificationId) {},
);
如果没有使用 firebase_auth ,那有两个选项,SMS Retriever API 和 SMS User Consent API 。
SmartAuth 是在 Flutter 上使用这些 API 的封装,它提供 Pinput 的自动填充。
SMS Retriever API
要使用 Retriever API 需要 signature (签名)应用,Pinput 会计算 Hash 值并在控制台打印出来, SMS 码会被自动处理,不需要用户的交互。
注意 Signature (签名)应用在调试模式和发布模式会有差异
return Pinput(
androidSmsAutofillMethod: AndroidSmsAutofillMethod.smsRetrieverApi,
);
打印签名的示例:Pinput: App Signature for SMS Retriever API Is: kg+TZ3A5qzS
SMS User Consent API
不需要 Signature (签名)应用,用户会被提示确认阅读信息。
return Pinput(
androidSmsAutofillMethod: AndroidSmsAutofillMethod.smsUserConsentApi,
);
SmartAuth
如果自动填充支持无法满足需求,可以使用 SmartAuth 实现自动填充,也就是可以通过显示原生 Android 对话框启用电话号码。
无需添加 SmartAuth 依赖,它已经被添加了
参考更多示例 模板
技巧
-
Controller
/// 创建 Controller
final pinController = TextEditingController();
/// 编码设置文本
pinController.setText('1222');
/// 添加输入字符,如果在使用自定义键盘,这是有用的。
pinController.append('1', 4);
/// 删除最后一个字符
pinController.delete();
/// 不能在 build 方法中调用 setText 、 append 、 delete ,这里只是说明。
return Pinput(
controller: pinController,
);
-
焦点
/// 创建 FocusNode
final pinputFocusNode = FocusNode();
/// 让 pinput 获得焦点
pinputFocusNode.requestFocus();
/// 让 pinput 失去焦点
pinputFocusNode.unfocus();
/// 不能在 build 方法中调用 requestFocus 、 unfocus ,这里只是说明。
return Pinput(
focusNode: pinputFocusNode,
);
-
验证
/// 创建 key
final formKey = GlobalKey<FormState>();
/// 手动验证
/// 不能在 build 方法中调用 validate ,这里只是说明。
formKey.currentState!.validate();
return Form(
key: formKey,
child: Pinput(
// 没有验证器
// 如果设置为 True ,不管验证器返什么结果都会是错误状态。
forceErrorState: true,
// 文本会在 Pinput 下面显示
errorText: 'Error',
/// ------------
/// 有验证器
/// 会在用户点击键盘的完成按钮或完成 Pinput 输入后自动验证。
pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,
validator: (pin) {
if (pin == '2224') return null;
/// 文本会在 Pinput 下面显示
return 'Pin is incorrect';
},
),
);
属性
本部分未翻译,属性项目较多,参考源码。
本文正在参加「金石计划」
转载自:https://juejin.cn/post/7219132624127918141