mobile_skt/lib/widgets/form_item/sk_number_input.dart

130 lines
4.0 KiB
Dart
Raw Normal View History

import 'package:flutter/material.dart';
2024-03-21 14:09:49 +08:00
import 'package:flutter/services.dart';
import 'package:sk_base_mobile/app_theme.dart';
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
class SkNumberInput<T> extends StatefulWidget {
final TextEditingController textController;
2024-04-01 17:35:34 +08:00
final Function(FocusNode)? onTap;
2024-03-26 11:35:39 +08:00
final Function(String)? onChanged;
2024-04-12 09:56:00 +08:00
final void Function(dynamic)? onTapOutside;
final Function(dynamic)? validator;
2024-04-01 17:35:34 +08:00
final bool isDense;
final EdgeInsetsGeometry? contentPadding;
final bool autoFocus;
final bool isRequired;
final String labelText;
final String? hint;
2024-04-12 09:56:00 +08:00
final ValueChanged<T>? onFieldSubmitted;
2024-04-07 17:32:46 +08:00
const SkNumberInput(
{super.key,
required this.textController,
this.onTap,
this.onChanged,
this.hint,
this.onTapOutside,
this.isRequired = false,
this.labelText = '',
this.onFieldSubmitted,
this.autoFocus = false,
this.contentPadding,
this.isDense = false,
this.validator});
2024-04-01 17:35:34 +08:00
@override
State<SkNumberInput> createState() => _SkNumberInputState<T>();
2024-04-01 17:35:34 +08:00
}
class _SkNumberInputState<T> extends State<SkNumberInput> {
2024-04-01 17:35:34 +08:00
late FocusNode focusNode = FocusNode();
@override
void initState() {
super.initState();
if (widget.autoFocus) {
WidgetsBinding.instance.addPostFrameCallback((_) {
focusNode.requestFocus();
});
}
}
@override
Widget build(BuildContext context) {
return TextFormField(
2024-04-01 17:35:34 +08:00
focusNode: focusNode,
onTap: () {
2024-04-02 16:22:21 +08:00
if (widget.onTap != null) {
2024-04-01 17:35:34 +08:00
widget.onTap!(focusNode);
}
},
controller: widget.textController,
onFieldSubmitted: (event) {
if (widget.onTapOutside != null) {
dynamic value;
if (T == double) {
value = double.tryParse(widget.textController.text);
widget.onTapOutside!(value as T);
} else {
value = int.tryParse(widget.textController.text);
}
if (widget.validator != null && !widget.validator!(value)) {
return;
}
widget.onTapOutside!(value as T);
}
},
onTapOutside: (event) {
if (widget.onTapOutside != null) {
2024-04-12 09:56:00 +08:00
dynamic value = widget.textController.text;
if (T == double) {
2024-04-12 09:56:00 +08:00
value = double.tryParse(widget.textController.text) ?? 0.0;
widget.onTapOutside!(value as T);
} else {
2024-04-12 09:56:00 +08:00
value = int.tryParse(widget.textController.text) ?? 0;
}
if (widget.validator != null && !widget.validator!(value)) {
return;
}
widget.onTapOutside!(value as T);
FocusScope.of(context).unfocus();
}
},
2024-04-01 17:35:34 +08:00
onChanged: widget.onChanged ?? (_) {},
2024-03-21 14:09:49 +08:00
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
2024-03-21 14:09:49 +08:00
inputFormatters: <TextInputFormatter>[
2024-03-26 11:35:39 +08:00
// 限制输入内容只能是数字和小数点不限制位数
FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,10}')),
2024-03-21 14:09:49 +08:00
],
decoration: InputDecoration(
2024-04-01 17:35:34 +08:00
contentPadding: widget.contentPadding,
isDense: widget.isDense,
2024-03-26 11:35:39 +08:00
// contentPadding: EdgeInsets.symmetric(vertical: ScreenAdaper.height(18)),
floatingLabelBehavior: FloatingLabelBehavior.always,
label: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
2024-04-01 17:35:34 +08:00
if (widget.isRequired)
2024-03-21 14:09:49 +08:00
Text(
"*",
2024-03-21 14:09:49 +08:00
style: TextStyle(
2024-03-28 17:18:46 +08:00
color: Colors.red, fontSize: ScreenAdaper.height(30)),
),
Text(
2024-04-01 17:35:34 +08:00
widget.labelText,
2024-03-28 17:18:46 +08:00
style: TextStyle(fontSize: ScreenAdaper.height(30)),
),
]),
focusedBorder: OutlineInputBorder(
borderSide:
const BorderSide(color: AppTheme.primaryColorLight, width: 2),
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15))),
2024-04-01 17:35:34 +08:00
hintText: widget.hint ?? '请输入',
),
);
}
}