v8
This commit is contained in:
215
lib/go_router/examples/input/input.dart
Normal file
215
lib/go_router/examples/input/input.dart
Normal file
@@ -0,0 +1,215 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'decoration/code_decoration.dart';
|
||||
import 'input_painter.dart';
|
||||
|
||||
typedef AsyncSubmit = Future<bool> Function(String value);
|
||||
|
||||
/// @desc 短信验证码输入框
|
||||
/// @time 2019-05-14 16:16
|
||||
/// @author Cheney
|
||||
class TolyCodeInput extends StatefulWidget {
|
||||
final int count;
|
||||
|
||||
final AsyncSubmit onSubmit;
|
||||
|
||||
final CodeDecoration decoration;
|
||||
|
||||
final TextInputType keyboardType;
|
||||
|
||||
final bool autoFocus;
|
||||
|
||||
final FocusNode? focusNode;
|
||||
|
||||
final TextInputAction textInputAction;
|
||||
|
||||
const TolyCodeInput(
|
||||
{this.count = 6,
|
||||
required this.onSubmit,
|
||||
this.decoration = const UnderlineDecoration(),
|
||||
this.keyboardType = TextInputType.number,
|
||||
this.focusNode,
|
||||
this.autoFocus = false,
|
||||
this.textInputAction = TextInputAction.done,
|
||||
super.key});
|
||||
|
||||
@override
|
||||
State createState() {
|
||||
return TolyCodeInputState();
|
||||
}
|
||||
}
|
||||
|
||||
class TolyCodeInputState extends State<TolyCodeInput>
|
||||
with SingleTickerProviderStateMixin {
|
||||
///输入监听器
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
late AnimationController _animaCtrl;
|
||||
late Animation<int> _animation;
|
||||
|
||||
late FocusNode _focusNode;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_focusNode = widget.focusNode ?? FocusNode();
|
||||
_controller.addListener(_listenValueChange);
|
||||
initAnimation();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void initAnimation() {
|
||||
_animaCtrl = AnimationController(
|
||||
duration: const Duration(milliseconds: 500),
|
||||
vsync: this,
|
||||
);
|
||||
_animation = IntTween(begin: 0, end: 255).animate(_animaCtrl)
|
||||
..addStatusListener(_stateChange);
|
||||
_animaCtrl.forward();
|
||||
}
|
||||
|
||||
void _listenValueChange() {
|
||||
submit(_controller.text);
|
||||
}
|
||||
|
||||
void submit(String text) async{
|
||||
if (text.length >= widget.count) {
|
||||
bool success = await widget.onSubmit.call(text.substring(0, widget.count));
|
||||
if(success){
|
||||
_focusNode.unfocus();
|
||||
}else{
|
||||
_controller.text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
/// Only execute when the controller is autoDispose.
|
||||
_controller.dispose();
|
||||
_animaCtrl.dispose();
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomPaint(
|
||||
foregroundPainter: InputPainter(
|
||||
RRectCodeDecoration(
|
||||
height: 56,
|
||||
strokeWidth: 1,
|
||||
activeColor: const Color(0xff010101),
|
||||
inactiveColor: const Color(0xffB6B6B6),
|
||||
cursorColor: Color(0xff3776E9),
|
||||
textStyle: TextStyle(color: Colors.black),
|
||||
cursorSize: Size(1, 24),
|
||||
),
|
||||
controller: _controller,
|
||||
count: widget.count,
|
||||
decoration: widget.decoration,
|
||||
alpha: _animation,
|
||||
),
|
||||
child: RepaintBoundary(
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
/// Fake the text style.
|
||||
style: const TextStyle(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
cursorColor: Colors.transparent,
|
||||
cursorWidth: 0.0,
|
||||
autocorrect: false,
|
||||
textAlign: TextAlign.center,
|
||||
enableInteractiveSelection: false,
|
||||
maxLength: widget.count,
|
||||
onSubmitted: submit,
|
||||
keyboardType: widget.keyboardType,
|
||||
focusNode: _focusNode,
|
||||
autofocus: widget.autoFocus,
|
||||
textInputAction: widget.textInputAction,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
counterText: '',
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 24),
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _stateChange(AnimationStatus status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
_animaCtrl.reverse();
|
||||
} else if (status == AnimationStatus.dismissed) {
|
||||
_animaCtrl.forward();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// 默认的样式
|
||||
const TextStyle defaultStyle = TextStyle(
|
||||
/// Default text color.
|
||||
color: Color(0x80000000),
|
||||
|
||||
/// Default text size.
|
||||
fontSize: 24.0,
|
||||
);
|
||||
|
||||
abstract class CodeDecoration {
|
||||
/// The style of painting text.
|
||||
final TextStyle? textStyle;
|
||||
|
||||
final ObscureStyle? obscureStyle;
|
||||
|
||||
const CodeDecoration({
|
||||
this.textStyle,
|
||||
this.obscureStyle,
|
||||
});
|
||||
}
|
||||
|
||||
/// The object determine the obscure display
|
||||
class ObscureStyle {
|
||||
/// Determine whether replace [obscureText] with number.
|
||||
final bool isTextObscure;
|
||||
|
||||
/// The display text when [isTextObscure] is true
|
||||
final String obscureText;
|
||||
|
||||
const ObscureStyle({
|
||||
this.isTextObscure = false,
|
||||
this.obscureText = '*',
|
||||
}) : assert(obscureText.length == 1);
|
||||
}
|
||||
|
||||
/// The object determine the underline color etc.
|
||||
class UnderlineDecoration extends CodeDecoration {
|
||||
/// The space between text and underline.
|
||||
final double gapSpace;
|
||||
|
||||
/// The color of the underline.
|
||||
final Color color;
|
||||
|
||||
/// The height of the underline.
|
||||
final double lineHeight;
|
||||
|
||||
/// The underline changed color when user enter pin.
|
||||
final Color? enteredColor;
|
||||
|
||||
const UnderlineDecoration({
|
||||
TextStyle? textStyle,
|
||||
ObscureStyle? obscureStyle,
|
||||
this.enteredColor = const Color(0xff3776E9),
|
||||
this.gapSpace = 15.0,
|
||||
this.color = const Color(0x24000000),
|
||||
this.lineHeight = 0.5,
|
||||
}) : super(
|
||||
textStyle: textStyle,
|
||||
obscureStyle: obscureStyle,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user