我撰寫了一個自定義文本欄位,用于在驗證器失去焦點時檢查它,其中包含一些 UI,例如錯誤文本和綠色選中圖示。在我需要根據其他 TextField 的資料執行一些自動填充之前,它們作業正常。
當用戶填寫郵政編碼時,將從 ChangeNotifierProvider 視圖模型中呼叫 API 并根據其更新狀態
user.prefectureName = data.prefectureName;
user.city = data.city;
user.address = data.address;
notifyListeners();
在 HookConsumerWidget 頁面中,我將狀態傳遞到自定義文本欄位中,如下所示
OCTextField(
text: user.prefectureName,
labelText: l10n.accountProfileEditPrefectureName,
errorText: "都道府県は必須項目です",
onChanged: (value) => user.prefectureName = value,
validator: (value) => value.isNotEmpty),
OCTextField(
text: user.city,
labelText: l10n.accountProfileEditCity,
errorText: "市區町村は必須項目です",
onChanged: (value) => user.city = value,
validator: (value) => value.isNotEmpty),
OCTextField(
text: user.address,
labelText: l10n.accountProfileEditAddress,
errorText: "丁目?番地は必須項目です",
onChanged: (value) => user.address = value,
validator: (value) => value.isNotEmpty),
但是,當狀態更改(user.prefectureName、user.city 和 user.address)時,我的自定義文本欄位將無法相應地反映更改。這是我的自定義文本欄位代碼的一部分
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import '../util/ext/string_ext.dart';
typedef Validator = bool Function(String value);
class OCTextField extends HookWidget {
const OCTextField(
{Key? key,
this.text = "",
this.labelText,
this.hintText,
this.errorText,
this.maxLines = 1,
this.maxLength,
this.sanitise = true,
this.onChanged,
this.validator})
: super(key: key);
final String text;
final String? labelText;
final String? hintText;
final String? errorText;
final int? maxLines;
final int? maxLength;
final bool sanitise;
final ValueChanged<String>? onChanged;
final Validator? validator;
@override
Widget build(BuildContext context) {
final _showError = useState(false);
final _controller = useTextEditingController(text: text);
final _checkIcon;
final unchecked =
const Icon(Icons.check_circle_outline, color: Colors.black26);
final checked = const Icon(Icons.check_circle, color: Colors.green);
if (validator != null) {
_checkIcon = useState(validator!(_controller.text) ? checked : unchecked);
} else {
_checkIcon = useState(checked);
}
return Focus(
child: TextField(
controller: _controller,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(1.0),
),
suffixIcon: _checkIcon.value,
labelText: labelText,
hintText: hintText,
errorText: _showError.value ? errorText : null,
),
maxLines: maxLines,
maxLength: maxLength,
onChanged: onChanged),
onFocusChange: (isFocused) {
if (isFocused) {
_showError.value = false;
_checkIcon.value = unchecked;
} else {
if (sanitise) {
_controller.text = _controller.text.sanitise();
onChanged!(_controller.text.sanitise());
}
if (validator != null) {
_showError.value = !validator!(_controller.text);
}
_checkIcon.value = _showError.value ? unchecked : checked;
}
});
}
}
我實際上閱讀了 useTextEditingController(text: text) 的檔案,它不會對文本更改做出反應。我嘗試替換useTextEditingController為TextEditingController,但它以某種奇怪的行為起作用 - 即使我洗掉了反射的預填充文本并移動另一個欄位,文本也會再次出現;游標表現得很奇怪,當我單擊該欄位時,它從預填充文本的開頭開始。
當我繼承 TextField 類并將 TextControllerEditor 直接初始化為 TextField 實體時,它可以完美地作業而沒有奇怪的問題。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class OutlinedTextField extends TextField {
OutlinedTextField(
{String? labelText,
String? text,
String? errorText,
String? hintText,
TextInputType keyboardType = TextInputType.text,
int maxLines = 1,
Icon? icon,
List<TextInputFormatter>? inputFormatters,
ValueChanged<String>? onChanged,
isDense = false})
: super(
controller: text == null ? null : TextEditingController(text: text),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(1.0),
),
labelText: labelText,
hintText: hintText,
errorText: errorText,
prefixIcon: icon,
isDense: isDense),
keyboardType: keyboardType,
maxLines: maxLines,
inputFormatters: inputFormatters,
onChanged: onChanged,
);
}
使用這種方法,我無法獲得控制器。我使用組合而不是繼承重構自定義文本欄位的原因是訪問 controller.text 以進行驗證 UI。我在這里犯了一些嚴重的錯誤或誤解了這個概念嗎?我無法弄清楚這種奇怪的行為。
uj5u.com熱心網友回復:
- 您必須在自定義文本欄位中添加可重用控制器
- 注意:您必須始終為每個文本欄位創建一個單獨的控制器
class CustomTextField extends StatelessWidget {
// created custom controller
TextEditingController controller;
String text;
CustomTextField({
required this.controller,
required this.text
});
@override
Widget build(BuildContext context) {
return TextField();
}
}
- 然后為每個文本檔案創建一個 textEditingController 并在 oninit 函式中對其進行初始化。
late TextEditingController text1 ;
late TextEditingController text2 ;
- 在自定義文本欄位中使用控制器
CustomTextField(controller: text1 ,text: "text1",),
CustomTextField(controller: text2 ,text: "text2",)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/431596.html
上一篇:如何在flutter中存盤SharedPreference值并將其傳遞給其他頁面?
下一篇:必須初始化不可為空的變數“相機”
