我创建了一个自定义文本字段,其中需要有以下内容:
因此,我创建了以下自定义文本字段:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
import 'package:myapp/app/components/material/icon.view.dart';
import 'package:myapp/app/components/text/text.view.dart';
import 'package:myapp/app/localizations/app_localizations.dart';
import 'package:myapp/theme/colors.extensions.dart';
import 'package:myapp/theme/icons.dart';
import 'package:myapp/theme/styling.extensions.dart';
class CustomTextField extends StatefulWidget {
CustomTextField({
super.key,
this.initialValue,
this.updateValue,
this.textEditingController,
required this.orientation,
});
dynamic initialValue;
Function? updateValue;
TextEditingController? textEditingController;
Orientation orientation;
@override
State<CustomTextField> createState() => _CustomTextFieldState();
}
class _CustomTextFieldState extends State<CustomTextField> {
TextEditingController controller = TextEditingController();
FocusNode focusNode = FocusNode();
@override
void initState() {
controller = TextEditingController(text: widget.initialValue == null ? null : '${widget.initialValue}');
super.initState();
}
@override
Widget build(BuildContext context) {
(widget.textEditingController ?? controller).selection =
TextSelection.fromPosition(TextPosition(offset: (widget.textEditingController ?? controller).text.length));
return SizedBox(
width: MediaQuery.of(context).size.width,
height: 55,
child: Stack(
children: [
KeyboardActions(
tapOutsideBehavior: TapOutsideBehavior.opaqueDismiss,
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
nextFocus: false,
actions: kIsWeb != true
? [
KeyboardActionsItem(
focusNode: focusNode,
displayArrows: false,
toolbarButtons: [
(node) {
return GestureDetector(
onTap: () {
node.unfocus();
},
child: Padding(
padding: CustomPadding.p10(),
child: CustomText(
AppLocalizations.instance.translate('Close'),
),
),
);
}
],
),
]
: [],
),
child: TextField(
focusNode: focusNode,
enableSuggestions: false,
autocorrect: false,
controller: widget.textEditingController ?? controller,
cursorColor: CustomColors.blue,
onChanged: (value) {
setState(() {
(widget.textEditingController ?? controller).text = value;
if (widget.updateValue != null) {
widget.updateValue!(value);
}
});
},
onSubmitted: (value) {
FocusManager.instance.primaryFocus?.unfocus();
},
style: CustomTextStyle.custom(fontSize: 24, color: Colors.black),
textAlignVertical: TextAlignVertical.top,
decoration: InputDecoration(
contentPadding: CustomPadding.ltrb(10, 8, 10 + ((widget.textEditingController ?? controller).text.isNotEmpty ? 28 : 0), 8),
isDense: true,
filled: true,
hintStyle: CustomTextStyle.custom(color: CustomColors.darkGrey, fontSize: 20),
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: CustomColors.blue, width: 2),
borderRadius: BorderRadius.circular(10),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: CustomColors.darkGrey,
width: 1.5,
),
borderRadius: BorderRadius.circular(10),
),
),
),
),
if ((widget.textEditingController ?? controller).text.isNotEmpty)
SizedBox(
height: 49,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: CustomPadding.only10(PaddingPosition.r),
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
HapticFeedback.heavyImpact();
if (widget.updateValue != null) {
widget.updateValue!('');
}
setState(() {
(widget.textEditingController ?? controller).text = '';
});
},
child: CustomIcon(
icon: SvgFont.xmark_solid,
color: CustomColors.red,
),
),
),
],
),
)
],
),
);
}
}
但是,这会导致光标出现问题,因为它一直移动到字符串的末尾,而不是停留在我正在写入的位置。我尝试删除所有自定义控制器管理和初始值,问题已修复,但我需要这些输入。此外,如果我不在构建函数中设置选择,文本字段会不断失去焦点,并且无法编写任何内容。
我想要我在开头列出的三个点,但我也想修复光标和选择,这样如果我想编辑字符串的中间部分,我可以做到这一点,而无需移动光标指向我输入的每个字符。
我怎样才能实现这个目标?
即使将光标放在中间,它总是在最后键入的原因是由于这一行:
@override
Widget build(BuildContext context) {
// Within the build method
(widget.textEditingController ?? controller).selection =
TextSelection.fromPosition(
TextPosition(
offset: (widget.textEditingController ?? controller).text.length),
);
每次构建小部件时,此行都会将光标位置设置到文本末尾,
现在,由于此代码位于
build
方法中,因此在每个小部件重建 (setState
) 时,它将重新触发
并将光标重新插入末尾。
要解决此问题,您可以将逻辑移至
onChanged
内,而不是 build
方法中:
onChanged: (value) {
final cursorPosition = (widget.textEditingController ?? controller).selection.baseOffset;
setState(() {
(widget.textEditingController ?? controller).text = value;
widget.updateValue?.call(value);
(widget.textEditingController ?? controller).selection = TextSelection.fromPosition(
TextPosition(offset: cursorPosition),
);
});
},