提交 e4efbda8 authored 作者: 祁增奎's avatar 祁增奎

初版提交

上级
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"fluttertoast","path":"/Users/mrqi/.pub-cache/hosted/pub.flutter-io.cn/fluttertoast-8.2.8/","native_build":true,"dependencies":[]}],"android":[{"name":"fluttertoast","path":"/Users/mrqi/.pub-cache/hosted/pub.flutter-io.cn/fluttertoast-8.2.8/","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[{"name":"fluttertoast","path":"/Users/mrqi/.pub-cache/hosted/pub.flutter-io.cn/fluttertoast-8.2.8/","dependencies":[]}]},"dependencyGraph":[{"name":"fluttertoast","dependencies":[]}],"date_created":"2025-04-24 14:46:53.353732","version":"3.19.6"}
\ No newline at end of file
## 0.0.1
* TODO: Describe initial release.
TODO: Add your license here.
<!--
This README describes the package. If you publish this package to pub.dev,
this README's contents appear on the landing page for your package.
For information about how to write a good package README, see the guide for
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).
For general information about developing packages, see the Dart guide for
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
and the Flutter guide for
[developing packages and plugins](https://flutter.dev/developing-packages).
-->
TODO: Put a short description of the package here that helps potential users
know whether this package might be useful for them.
## Features
TODO: List what your package can do. Maybe include images, gifs, or videos.
## Getting started
TODO: List prerequisites and provide or point to information on how to
start using the package.
## Usage
TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.
```dart
const like = 'sample';
```
## Additional information
TODO: Tell users more about the package: where to find more information, how to
contribute to the package, how to file issues, what response they can expect
from the package authors, and more.
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
library clx_verification_code;
/// 公共控制器
export 'code_manage/clx_code_manage_logic.dart';
/// -------公共View---------
export 'views/clx_line_code_manage_view.dart';
export 'views/clx_page_code_manage_view.dart';
/// -------公共Package---------
export 'package:get/get.dart';
export 'package:fluttertoast/fluttertoast.dart';
/// -------公共Widget---------
export 'widgets/input_widget/code_input_paint.dart';
export 'widgets/input_widget/code_input_view.dart';
export 'widgets/tips_widget/no_receive_resend_sms_view.dart';
export 'widgets/tips_widget/no_receive_sms_view.dart';
export 'widgets/tips_widget/no_receive_voice_view.dart';
/// -------公共Utils---------
export 'utils/line_code_manage_config.dart';
export 'utils/page_code_manage_config.dart';
export 'utils/code_send_enum.dart';
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:fluttertoast/fluttertoast.dart';
import '../utils/code_send_enum.dart';
class CLXCodeManageLogic extends GetxController {
CLXCodeManageLogic(
{this.maxLength = 6,
this.isFirstResponsed = false,
this.countdownTime = 60});
/// 验证码长度
final int maxLength;
/// 倒计时时间
final int countdownTime;
/// 是否是成为第一响应者
final bool isFirstResponsed;
/// 验证码输入框焦点
final FocusNode codeInoutFocus = FocusNode();
/// 验证码输入框控制器
final TextEditingController codeInoutCtrl = TextEditingController();
/// 倒计时
RxInt countdown = 0.obs;
/// 定时器
Timer? timer;
/// 获取短信验证码
Future<bool?> Function()? getSmsVerificationCode;
/// 获取语音验证码
Future<bool?> Function()? obtainVoiceVerificationCode;
/// 校验验证码输入是否有误
Future<String?> Function(String code)? verifyCode;
/// 联系客服点击事件
Future Function()? contactCustomerService;
/// 验证码校验错误信息
RxString verifyCodeError = ''.obs;
/// 获取验证码按钮文案
RxString codeSendBtn = '获取验证码'.obs;
/// 验证码发送状态
Rx<CodeSendType> codeSendType = CodeSendType.none.obs;
/// 是否展示提示信息模块
RxBool isShowTip = false.obs;
/// 刷新页面需要
RxString refreshPage = ''.obs;
@override
void onInit() {
super.onInit();
codeInoutCtrl.addListener(_verifyCodeInput);
countdown.value = countdownTime;
if (isFirstResponsed) {
codeInoutFocus.requestFocus();
}
}
/// 校验验证码
_verifyCodeInput() async {
handleTipInfo();
update();
refreshPage.value = codeInoutCtrl.text;
if (codeInoutCtrl.text.length != maxLength) {
return;
}
final result = await verifyCode?.call(codeInoutCtrl.text) ?? '';
verifyCodeError.value = result;
}
/// 外部调用开启定时器
startTimerAndChangeType() {
_startCountdown();
handleCodeSendType();
}
/// 发送短信验证码
sendSmsCode() async {
if (countdown.value != countdownTime) {
return;
}
final result = await getSmsVerificationCode?.call();
if (result == true) {
handleCodeSendType();
_startCountdown();
}
}
/// 发送语音验证码
sendVoiceCode() async {
if (countdown.value != countdownTime) {
return;
}
final result = await obtainVoiceVerificationCode?.call();
Fluttertoast.showToast(
msg: '即将向您电话播报',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 2,
);
if (result == true) {
handleCodeSendType(isSmsSend: false);
_startCountdown(isSmsSend: false);
}
}
/// 联系客服
contactService() async {
await contactCustomerService?.call();
}
/// 开启倒计时
_startCountdown({bool isSmsSend = true}) {
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (countdown.value == 0) {
timer.cancel();
codeSendBtn.value = '';
countdown.value = countdownTime;
handleCodeSendType(isSmsSend: isSmsSend);
handleTipInfo();
} else {
countdown.value--;
codeSendBtn.value = '已发送${countdown.value}s';
}
});
}
/// 处理验证码发送状态
handleCodeSendType({bool isSmsSend = true}) {
switch (codeSendType.value) {
case CodeSendType.none:
codeSendType.value = CodeSendType.firstSendSmsCode;
break;
case CodeSendType.firstSendSmsCode:
codeSendType.value = CodeSendType.notReceiveSmsCode;
break;
case CodeSendType.notReceiveSmsCode:
if (isSmsSend) {
codeSendType.value = CodeSendType.resendSmsCode;
} else {
codeSendType.value = CodeSendType.firstSendVoiceCode;
}
break;
case CodeSendType.resendSmsCode:
codeSendType.value = CodeSendType.notReceiveResendSmsCode;
break;
case CodeSendType.notReceiveResendSmsCode:
codeSendType.value = CodeSendType.firstSendVoiceCode;
break;
case CodeSendType.firstSendVoiceCode:
codeSendType.value = CodeSendType.notReceiveVoiceCode;
break;
case CodeSendType.notReceiveVoiceCode:
codeSendType.value = CodeSendType.resendVoiceCode;
break;
case CodeSendType.resendVoiceCode:
codeSendType.value = CodeSendType.notReceiveResendVoiceCode;
break;
case CodeSendType.notReceiveResendVoiceCode:
codeSendType.value = CodeSendType.resendVoiceCode;
break;
default:
codeSendType.value = CodeSendType.notReceiveResendVoiceCode;
break;
}
}
/// 处理提示信息
handleTipInfo() {
/// 如果输入框内容不为空,则不展示提示信息
isShowTip.value =
codeInoutCtrl.text.isEmpty && countdown.value == countdownTime;
}
}
enum CodeSendType {
/// 未发送验证码
none,
/// 首次发送验证码
firstSendSmsCode,
/// 首次发送短信验证码,超时未收到,需要展示重新发动短信验证码按钮以及获取语音验证码按钮
notReceiveSmsCode,
/// 重新发送验短息证码
resendSmsCode,
/// 重新发送短信验证码,超时未收到,只能展示获取语音验证码按钮
notReceiveResendSmsCode,
/// 首次发送语音验证码
firstSendVoiceCode,
/// 首次发送语音验证码,超时未收到,只展示获取语音验证码按钮
notReceiveVoiceCode,
/// 重新发送语音证码
resendVoiceCode,
/// 重新发送语音验证码,超时未收到,需要展示获取语音验证码按钮以及联系人工服务按钮
notReceiveResendVoiceCode,
}
extension CodeSendTypeExtension on CodeSendType {
/// 是否发送过验证码
bool get isUnSend => this == CodeSendType.none;
/// 是否已发送过验证码
bool get isSend =>
this == CodeSendType.firstSendSmsCode ||
this == CodeSendType.firstSendVoiceCode ||
this == CodeSendType.resendSmsCode ||
this == CodeSendType.resendVoiceCode;
/// 是否短信验证码
bool get isSms =>
this == CodeSendType.firstSendSmsCode ||
this == CodeSendType.resendSmsCode;
/// 是否语音验证码
bool get isVoice =>
this == CodeSendType.firstSendVoiceCode ||
this == CodeSendType.resendVoiceCode;
/// 是否首次发送
bool get isFirst =>
this == CodeSendType.firstSendSmsCode ||
this == CodeSendType.firstSendVoiceCode;
/// 是否第二次发送
bool get isSecond =>
this == CodeSendType.resendSmsCode ||
this == CodeSendType.resendVoiceCode;
/// 是否展示联系客服按钮
bool get isShowContact => this == CodeSendType.notReceiveResendVoiceCode;
}
extension CodeSendTypeCode on CodeSendType {
int get code {
switch (this) {
case CodeSendType.none:
return 0;
case CodeSendType.firstSendSmsCode:
return 1;
case CodeSendType.notReceiveSmsCode:
return 2;
case CodeSendType.resendSmsCode:
return 3;
case CodeSendType.notReceiveResendSmsCode:
return 4;
case CodeSendType.firstSendVoiceCode:
return 5;
case CodeSendType.notReceiveVoiceCode:
return 6;
case CodeSendType.resendVoiceCode:
return 7;
case CodeSendType.notReceiveResendVoiceCode:
return 8;
}
}
}
import 'package:flutter/widgets.dart';
class LineCodeManageConfig {
/// 外层容器
Decoration? decoration;
/// 外边距
EdgeInsetsGeometry? margin;
/// 内边距
EdgeInsetsGeometry? padding;
/// 输入框是否紧贴
bool isCollapsed;
/// 提示文字
String? hintText;
/// 提示文字样式
TextStyle? hintStyle;
/// 输入框文字样式
TextStyle? style;
/// 倒计时文字样式
TextStyle? countdownStyle;
/// 倒计时文字样式
TextStyle? codeSendStyle;
/// 重新获取文字样式
TextStyle? reSendStyle;
/// 提示文字样式
TextStyle? tipsStyle;
/// 错误提示文字样式
TextStyle? errorStyle;
/// 语音发送文字样式
TextStyle? voiceSendStyle;
/// 联系客服文字样式
TextStyle? contactStyle;
LineCodeManageConfig({
this.decoration = const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(6)),
color: Color(0xffF7F8FA),
),
this.margin = const EdgeInsets.symmetric(horizontal: 30),
this.padding = const EdgeInsets.symmetric(horizontal: 30),
this.isCollapsed = false,
this.hintText,
this.hintStyle = const TextStyle(
color: Color(0xffC9CDD4), fontSize: 14, fontWeight: FontWeight.w400),
this.style = const TextStyle(
color: Color(0xff333C4C), fontSize: 15, fontWeight: FontWeight.w500),
this.countdownStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 14,
fontWeight: FontWeight.w500,
),
this.codeSendStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 14,
fontWeight: FontWeight.w500,
),
this.reSendStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 12,
fontWeight: FontWeight.w600,
),
this.tipsStyle = const TextStyle(
color: Color(0xff86909C),
fontSize: 12,
fontWeight: FontWeight.w400,
),
this.errorStyle = const TextStyle(
color: Color(0xffFF4D4F),
fontSize: 12,
fontWeight: FontWeight.w400,
),
this.voiceSendStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 12,
fontWeight: FontWeight.w600,
),
this.contactStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 12,
fontWeight: FontWeight.w600,
),
});
}
import 'package:flutter/widgets.dart';
class PageCodeManageConfig {
/// 外层容器
Decoration? decoration;
/// 外边距
EdgeInsetsGeometry? margin;
/// 内边距
EdgeInsetsGeometry? padding;
/// 输入框是否紧贴
bool isCollapsed;
/// 提示文字
String? hintText;
/// 提示文字样式
TextStyle? hintStyle;
/// 输入框文字样式
TextStyle? style;
/// 倒计时文字样式
TextStyle? countdownStyle;
/// 倒计时文字样式
TextStyle? codeSendStyle;
/// 重新获取文字样式
TextStyle? reSendStyle;
/// 提示文字样式
TextStyle? tipsStyle;
/// 错误提示文字样式
TextStyle? errorStyle;
/// 语音发送文字样式
TextStyle? voiceSendStyle;
/// 联系客服文字样式
TextStyle? contactStyle;
/// 是否隐藏输入内容
final bool obscureText;
/// 输入框背景色
final Color inputRectBg;
/// 输入框间距
final double runSpance;
/// 输入框圆角
final double radius;
PageCodeManageConfig({
this.decoration = const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(6)),
color: Color(0xffF7F8FA),
),
this.margin = const EdgeInsets.symmetric(horizontal: 30),
this.padding = const EdgeInsets.symmetric(horizontal: 30),
this.isCollapsed = false,
this.hintText,
this.hintStyle = const TextStyle(
color: Color(0xffC9CDD4), fontSize: 14, fontWeight: FontWeight.w400),
this.style = const TextStyle(
color: Color(0xff333C4C), fontSize: 15, fontWeight: FontWeight.w500),
this.countdownStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 14,
fontWeight: FontWeight.w500,
),
this.codeSendStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 14,
fontWeight: FontWeight.w500,
),
this.reSendStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 12,
fontWeight: FontWeight.w600,
),
this.tipsStyle = const TextStyle(
color: Color(0xff86909C),
fontSize: 12,
fontWeight: FontWeight.w400,
),
this.errorStyle = const TextStyle(
color: Color(0xffFF4D4F),
fontSize: 12,
fontWeight: FontWeight.w400,
),
this.voiceSendStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 12,
fontWeight: FontWeight.w600,
),
this.contactStyle = const TextStyle(
color: Color(0xff4F4535),
fontSize: 12,
fontWeight: FontWeight.w600,
),
this.obscureText = false,
this.inputRectBg = const Color(0xffF2F3F5),
this.runSpance = 8,
this.radius = 8,
});
}
import 'package:clx_verification_code/utils/code_send_enum.dart';
import 'package:flutter/material.dart';
import '../clx_verification_code.dart';
class CLXLineCodeManageView extends StatelessWidget {
const CLXLineCodeManageView({
super.key,
required this.loigc,
required this.config,
this.disabled = false,
});
/// 页面状态变化处理控制器
final CLXCodeManageLogic loigc;
/// 是否禁用
final bool disabled;
/// 样式配置
final LineCodeManageConfig config;
@override
Widget build(BuildContext context) {
return Container(
margin: config.margin,
padding: config.padding,
decoration: config.decoration,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: TextField(
controller: loigc.codeInoutCtrl,
keyboardType: TextInputType.number,
maxLength: loigc.maxLength,
style: config.style,
enabled: !disabled,
enableInteractiveSelection: false,
decoration: InputDecoration(
isCollapsed: config.isCollapsed,
counterText: '',
hintText: config.hintText,
hintStyle: config.hintStyle,
border: InputBorder.none,
),
),
),
const SizedBox(width: 10),
Obx(
() => Visibility(
visible: loigc.codeSendBtn.value.isNotEmpty,
child: GestureDetector(
onTap: loigc.sendSmsCode,
child: Text(
loigc.codeSendBtn.value,
style: loigc.codeSendType.value.isUnSend
? config.countdownStyle
: config.codeSendStyle,
),
),
),
),
],
),
Obx(
() => Visibility(
visible: loigc.verifyCodeError.value.isNotEmpty,
child: Column(
children: [
const SizedBox(height: 5),
Text(
loigc.verifyCodeError.value,
style: config.errorStyle,
),
],
),
),
),
Obx(
() => Visibility(
visible: loigc.isShowTip.value,
child: Column(
children: [
/// 展示重新发送验证码按钮以及获取语音验证码按钮
if (loigc.codeSendType.value ==
CodeSendType.notReceiveSmsCode)
NoReceiveSmsView(
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
voiceSendStyle: config.voiceSendStyle,
sendSmsCode: loigc.sendSmsCode,
sendVoiceCode: loigc.sendVoiceCode,
),
/// 展示没有收到二次发送的验证码的提示
if (loigc.codeSendType.value ==
CodeSendType.notReceiveResendSmsCode)
NoReceiveResendSmsView(
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
sendVoiceCode: loigc.sendVoiceCode,
),
/// 展示没有收到首次发送的语音验证码的提示
if (loigc.codeSendType.value ==
CodeSendType.notReceiveVoiceCode ||
loigc.codeSendType.value ==
CodeSendType.notReceiveResendVoiceCode)
NoReceiveVoiceView(
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
contactStyle: config.contactStyle,
sendVoiceCode: loigc.sendVoiceCode,
contactService: loigc.contactService,
isShowContact: loigc.codeSendType.value ==
CodeSendType.notReceiveResendVoiceCode,
),
],
),
),
),
],
),
);
}
}
import 'package:flutter/widgets.dart';
import '../clx_verification_code.dart';
class CLXPageCodeManageView extends StatelessWidget {
const CLXPageCodeManageView({
super.key,
required this.loigc,
required this.config,
});
/// 页面状态变化处理控制器
final CLXCodeManageLogic loigc;
/// 是否隐藏输入内容
final PageCodeManageConfig config;
@override
Widget build(BuildContext context) {
return Container(
margin: config.margin,
padding: config.padding,
decoration: config.decoration,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GetBuilder(
init: loigc,
builder: (controller) {
return CodeInputView(
controller: loigc.codeInoutCtrl,
focusNode: loigc.codeInoutFocus,
obscureText: config.obscureText,
maxLength: loigc.maxLength,
inputRectBg: config.inputRectBg,
runSpance: config.runSpance,
radius: config.radius,
);
},
),
Obx(
() => Visibility(
visible: loigc.verifyCodeError.value.isNotEmpty,
child: Column(
children: [
const SizedBox(height: 5),
Text(
loigc.verifyCodeError.value,
style: config.errorStyle,
),
],
),
),
),
Obx(
() => Visibility(
visible: loigc.isShowTip.value,
child: Column(
children: [
/// 展示重新发送验证码按钮以及获取语音验证码按钮
if (loigc.codeSendType.value ==
CodeSendType.notReceiveSmsCode)
NoReceiveSmsView(
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
voiceSendStyle: config.voiceSendStyle,
sendSmsCode: loigc.sendSmsCode,
sendVoiceCode: loigc.sendVoiceCode,
),
/// 展示没有收到二次发送的验证码的提示
if (loigc.codeSendType.value ==
CodeSendType.notReceiveResendSmsCode)
NoReceiveResendSmsView(
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
sendVoiceCode: loigc.sendVoiceCode,
),
/// 展示没有收到首次发送的语音验证码的提示
if (loigc.codeSendType.value ==
CodeSendType.notReceiveVoiceCode ||
loigc.codeSendType.value ==
CodeSendType.notReceiveResendVoiceCode)
NoReceiveVoiceView(
tipsStyle: config.tipsStyle,
reSendStyle: config.reSendStyle,
contactStyle: config.contactStyle,
sendVoiceCode: loigc.sendVoiceCode,
contactService: loigc.contactService,
isShowContact: loigc.codeSendType.value ==
CodeSendType.notReceiveResendVoiceCode,
),
],
),
),
),
],
),
);
}
}
import 'package:flutter/material.dart';
class CodeInputPaint extends CustomPainter {
const CodeInputPaint({
this.text,
this.bgColor = const Color(0xffF2F3F5),
this.runSpance = 8,
this.length = 6,
this.radius = 8,
});
final String? text;
//背景颜色
final Color bgColor;
//间隔
final double runSpance;
// 输入框个数
final int length;
// 圆角半径
final double radius;
@override
void paint(Canvas canvas, Size size) {
var sizeWidth = (size.width - runSpance * (length - 1)) / length;
// 绘制方框
for (var i = 0; i < length; i++) {
var rect = _Rect(
x: sizeWidth * i + runSpance * i,
y: 0,
width: sizeWidth,
height: sizeWidth,
);
_drawCircularRect(canvas, rect);
}
// 绘制文字
if (text != null) {
for (var i = 0; i < text!.length; i++) {
var textPainter = TextPainter(
text: TextSpan(
text: text![i],
style: TextStyle(
color: Colors.red,
fontSize: sizeWidth * 0.6,
),
),
textDirection: TextDirection.ltr,
);
textPainter.layout();
textPainter.paint(
canvas,
Offset(
sizeWidth * i +
runSpance * i +
sizeWidth / 2 -
textPainter.width / 2,
sizeWidth / 2 - textPainter.height / 2),
);
}
}
}
void _drawCircularRect(Canvas canvas, _Rect rect) {
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(rect.x, rect.y, rect.width, rect.height),
Radius.circular(radius),
),
Paint()
..color = bgColor
..style = PaintingStyle.fill,
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return !(oldDelegate is CodeInputPaint && oldDelegate.text == text);
}
}
class _Rect {
final double x;
final double y;
final double width;
final double height;
const _Rect({
required this.x,
required this.y,
required this.width,
required this.height,
});
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'code_input_paint.dart';
class CodeInputView extends StatelessWidget {
const CodeInputView({
super.key,
required this.controller,
required this.focusNode,
this.obscureText = false,
this.inputRectBg = const Color(0xffF2F3F5),
this.maxLength = 6,
this.runSpance = 8,
this.radius = 8,
});
final TextEditingController controller;
final FocusNode focusNode;
final bool obscureText; //是否隐藏输入内容
final Color inputRectBg; //输入框背景色
final int maxLength; //输入长度
final double runSpance; //输入框间距
final double radius; //输入框圆角
@override
Widget build(BuildContext context) {
final inputHeight = (MediaQuery.of(context).size.width -
(40 + runSpance * (maxLength - 1))) /
maxLength;
return CustomPaint(
foregroundPainter: CodeInputPaint(
text: obscureText
? controller.text.replaceAll(RegExp(r'\d'), '*')
: controller.text,
bgColor: inputRectBg,
runSpance: runSpance,
length: maxLength,
radius: radius,
),
child: TextField(
controller: controller,
maxLength: maxLength,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
showCursor: false,
enableSuggestions: false,
focusNode: focusNode,
enableInteractiveSelection: false,
style: const TextStyle(color: Colors.white),
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
isCollapsed: true,
suffix: SizedBox(height: inputHeight),
border: InputBorder.none,
counterText: '',
),
),
);
}
}
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
class NoReceiveResendSmsView extends StatelessWidget {
const NoReceiveResendSmsView({
super.key,
this.reSendStyle,
this.tipsStyle,
this.sendVoiceCode,
});
/// 重新获取文字样式
final TextStyle? reSendStyle;
/// 提示文字样式
final TextStyle? tipsStyle;
/// 发送语音验证码
final GestureTapCallback? sendVoiceCode;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: '没有收到短信?',
style: tipsStyle,
),
const WidgetSpan(child: SizedBox(width: 5)),
TextSpan(
text: '获取语音验证码',
style: reSendStyle,
recognizer: TapGestureRecognizer()..onTap = sendVoiceCode,
),
],
),
),
);
}
}
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
class NoReceiveSmsView extends StatelessWidget {
const NoReceiveSmsView({
super.key,
this.reSendStyle,
this.tipsStyle,
this.voiceSendStyle,
this.sendSmsCode,
this.sendVoiceCode,
});
/// 重新获取文字样式
final TextStyle? reSendStyle;
/// 提示文字样式
final TextStyle? tipsStyle;
/// 语音发送文字样式
final TextStyle? voiceSendStyle;
/// 发送短信验证码
final GestureTapCallback? sendSmsCode;
/// 发送语音验证码
final GestureTapCallback? sendVoiceCode;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
children: [
RichText(
text: TextSpan(
children: [
TextSpan(
text: '没有收到短信?',
style: tipsStyle,
),
const WidgetSpan(child: SizedBox(width: 5)),
TextSpan(
text: '重新获取',
style: reSendStyle,
recognizer: TapGestureRecognizer()..onTap = sendSmsCode,
),
],
),
),
const Spacer(),
GestureDetector(
onTap: sendVoiceCode,
child: Text(
'获取语音验证码',
style: voiceSendStyle,
),
),
],
),
);
}
}
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
class NoReceiveVoiceView extends StatelessWidget {
const NoReceiveVoiceView(
{super.key,
this.reSendStyle,
this.tipsStyle,
this.contactStyle,
required this.isShowContact,
this.contactService,
this.sendVoiceCode});
/// 重新获取文字样式
final TextStyle? reSendStyle;
/// 提示文字样式
final TextStyle? tipsStyle;
/// 联系客服文字样式
final TextStyle? contactStyle;
/// 是否显示联系客服
final bool isShowContact;
/// 联系客服
final GestureTapCallback? contactService;
/// 发送语音验证码
final GestureTapCallback? sendVoiceCode;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
children: [
Expanded(
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: '没有收到语音?',
style: tipsStyle,
),
const WidgetSpan(child: SizedBox(width: 5)),
TextSpan(
text: '重新获取',
style: reSendStyle,
recognizer: TapGestureRecognizer()..onTap = sendVoiceCode,
),
],
),
),
),
if (isShowContact) ...[
const SizedBox(width: 10),
GestureDetector(
onTap: contactService,
child: Text(
'联系人工服务',
style: contactStyle,
),
),
],
],
),
);
}
}
name: clx_verification_code
description: "A new Flutter package project."
version: 0.0.1
homepage:
environment:
sdk: '>=3.3.4 <4.0.0'
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
# 状态管理
get: ^4.3.7
# 吐司管理
fluttertoast: ^8.2.4
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论