211 lines
5.6 KiB
Dart
211 lines
5.6 KiB
Dart
|
|
|
||
|
|
import 'package:flutter/material.dart';
|
||
|
|
import 'package:flutter/services.dart';
|
||
|
|
|
||
|
|
class LoginPhoneTextField extends StatelessWidget {
|
||
|
|
const LoginPhoneTextField(
|
||
|
|
{Key? key, required this.controller, this.helperText, this.rightWidget})
|
||
|
|
: super(key: key);
|
||
|
|
|
||
|
|
final TextEditingController controller;
|
||
|
|
final String? helperText;
|
||
|
|
final Widget? rightWidget;
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
Widget textField = SizedBox(
|
||
|
|
height: 40,
|
||
|
|
child: TextFieldBase(
|
||
|
|
keyboardType: TextInputType.number,
|
||
|
|
leftWidget: const Padding(
|
||
|
|
padding: EdgeInsets.only(left: 10),
|
||
|
|
child: Icon(
|
||
|
|
Icons.perm_contact_calendar_sharp,
|
||
|
|
color: Colors.grey,
|
||
|
|
size: 20,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
rightWidget: rightWidget,
|
||
|
|
hintText: '请输入账号',
|
||
|
|
style: const TextStyle(color: Colors.white),
|
||
|
|
controller: controller,
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
return helperText == null
|
||
|
|
? textField
|
||
|
|
: Column(
|
||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
|
children: [
|
||
|
|
textField,
|
||
|
|
Padding(
|
||
|
|
padding: const EdgeInsets.only(top: 5),
|
||
|
|
child: Text(
|
||
|
|
helperText!,
|
||
|
|
style: const TextStyle(fontSize: 12, color: Colors.grey),
|
||
|
|
),
|
||
|
|
)
|
||
|
|
],
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class LoginPasswordTextField extends StatefulWidget {
|
||
|
|
const LoginPasswordTextField(
|
||
|
|
{Key? key,
|
||
|
|
required this.controller,
|
||
|
|
this.hintText = '请输入密码',
|
||
|
|
this.onSubmitted})
|
||
|
|
: super(key: key);
|
||
|
|
|
||
|
|
final TextEditingController controller;
|
||
|
|
final String hintText;
|
||
|
|
final ValueChanged<String>? onSubmitted;
|
||
|
|
|
||
|
|
@override
|
||
|
|
State<LoginPasswordTextField> createState() => _LoginPasswordTextFieldState();
|
||
|
|
}
|
||
|
|
|
||
|
|
class _LoginPasswordTextFieldState extends State<LoginPasswordTextField> {
|
||
|
|
bool hideCancel = true;
|
||
|
|
bool obsureText = true;
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
Widget cancel = Offstage(
|
||
|
|
offstage: hideCancel,
|
||
|
|
child: TextButton(
|
||
|
|
style: ButtonStyle(
|
||
|
|
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
||
|
|
),
|
||
|
|
onPressed: () {
|
||
|
|
setState(() {
|
||
|
|
obsureText = !obsureText;
|
||
|
|
});
|
||
|
|
},
|
||
|
|
child: Icon(
|
||
|
|
Icons.remove_red_eye_rounded,
|
||
|
|
color: Colors.grey,
|
||
|
|
size: 20,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
widget.controller.addListener(() {
|
||
|
|
setState(() {
|
||
|
|
hideCancel = !widget.controller.text.isNotEmpty;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
return SizedBox(
|
||
|
|
height: 40,
|
||
|
|
child: TextFieldBase(
|
||
|
|
hintText: widget.hintText,
|
||
|
|
controller: widget.controller,
|
||
|
|
obsureText: obsureText,
|
||
|
|
onSubmitted: widget.onSubmitted,
|
||
|
|
leftWidget: const Padding(
|
||
|
|
padding: EdgeInsets.only(left: 10),
|
||
|
|
child: Icon(
|
||
|
|
Icons.lock_sharp,
|
||
|
|
color: Colors.grey,
|
||
|
|
size: 20,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
style: const TextStyle(color: Colors.white),
|
||
|
|
rightWidget: cancel,
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class TextFieldBase extends StatefulWidget {
|
||
|
|
const TextFieldBase(
|
||
|
|
{Key? key,
|
||
|
|
this.leftWidget,
|
||
|
|
this.rightWidget,
|
||
|
|
this.hintText = '',
|
||
|
|
required this.controller,
|
||
|
|
this.obsureText = false,
|
||
|
|
this.keyboardType,
|
||
|
|
this.textAlign = TextAlign.start,
|
||
|
|
this.onChanged,
|
||
|
|
this.onSubmitted,
|
||
|
|
this.inputFormatters,
|
||
|
|
this.focusNode,
|
||
|
|
this.decoration,
|
||
|
|
this.style,
|
||
|
|
this.noFocusSubmitted = false})
|
||
|
|
: super(key: key);
|
||
|
|
|
||
|
|
final TextEditingController controller;
|
||
|
|
final FocusNode? focusNode;
|
||
|
|
final Widget? leftWidget;
|
||
|
|
final Widget? rightWidget;
|
||
|
|
final InputDecoration? decoration;
|
||
|
|
final TextStyle? style;
|
||
|
|
final TextInputType? keyboardType;
|
||
|
|
final String hintText;
|
||
|
|
/// 暗文
|
||
|
|
final bool obsureText;
|
||
|
|
final TextAlign textAlign;
|
||
|
|
final List<TextInputFormatter>? inputFormatters;
|
||
|
|
/// 失去焦点是否回调
|
||
|
|
final bool noFocusSubmitted;
|
||
|
|
final ValueChanged<String>? onChanged;
|
||
|
|
final ValueChanged<String>? onSubmitted;
|
||
|
|
|
||
|
|
@override
|
||
|
|
State<TextFieldBase> createState() => _TextFieldBaseState();
|
||
|
|
}
|
||
|
|
|
||
|
|
class _TextFieldBaseState extends State<TextFieldBase> {
|
||
|
|
late FocusNode focusNode;
|
||
|
|
|
||
|
|
@override
|
||
|
|
void initState() {
|
||
|
|
super.initState();
|
||
|
|
|
||
|
|
focusNode = widget.focusNode ?? FocusNode();
|
||
|
|
|
||
|
|
if (widget.onSubmitted != null && widget.noFocusSubmitted){
|
||
|
|
focusNode.addListener(() {
|
||
|
|
if (focusNode.hasFocus == false){
|
||
|
|
widget.onSubmitted!(widget.controller.text);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
final decoration = widget.decoration ??
|
||
|
|
InputDecoration(
|
||
|
|
prefixIcon: widget.leftWidget,
|
||
|
|
prefixIconConstraints: const BoxConstraints(minWidth: 4),
|
||
|
|
suffixIcon: widget.rightWidget,
|
||
|
|
hintText: widget.hintText,
|
||
|
|
hintStyle: const TextStyle(color: Colors.grey),
|
||
|
|
border: MaterialStateOutlineInputBorder.resolveWith((states) =>
|
||
|
|
const OutlineInputBorder(
|
||
|
|
borderSide: BorderSide(color: Colors.grey))),
|
||
|
|
contentPadding:
|
||
|
|
const EdgeInsets.only(left: 0, top: 0, bottom: 0, right: 15),
|
||
|
|
);
|
||
|
|
|
||
|
|
return TextField(
|
||
|
|
focusNode: focusNode,
|
||
|
|
controller: widget.controller,
|
||
|
|
inputFormatters: widget.inputFormatters,
|
||
|
|
style: widget.style ?? const TextStyle(fontSize: 14),
|
||
|
|
keyboardType: widget.keyboardType,
|
||
|
|
obscureText: widget.obsureText,
|
||
|
|
textAlign: widget.textAlign,
|
||
|
|
cursorColor: Colors.blue,
|
||
|
|
onChanged: widget.onChanged,
|
||
|
|
onSubmitted: widget.onSubmitted,
|
||
|
|
decoration: decoration,
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|