TextEditingController的实现
TextEditingValue.empty) 表示,如果外部传入的value值不是null,就以value赋值,如果value是null,就使用TextEditingValue的空值来赋值。TextEditingController 继承 ValueNotifier ,在TextEditingController 中可以监听TextEditingValue跟这个类的值的变化,构建时,通过supe
class TextEditingController extends ValueNotifier<TextEditingValue> {
TextEditingController({ String? text })
: super(text == null ? TextEditingValue.empty : TextEditingValue(text: text));
}
TextEditingController 继承 ValueNotifier ,在TextEditingController 中可以监听TextEditingValue跟这个类的值的变化,构建时,通过super去继承TextEditingValue的text属性值。
其中,ValueNotifier 类有一个value属性,这个属性的类型通过中传入,xx就是这个value的类型。
class TextEditingController extends ValueNotifier<TextEditingValue> {
/// ... 省略代码
TextEditingController.fromValue(TextEditingValue? value)
: assert(
value == null || !value.composing.isValid || value.isComposingRangeValid,
'New TextEditingValue $value has an invalid non-empty composing range '
'${value.composing}. It is recommended to use a valid composing range, '
'even for readonly text fields.',
),
super(value ?? TextEditingValue.empty);
}
TextEditingController.fromValue 给外部提供一个方法,用于修改TextEditingController中的数据,TextEditingValue是传入的model模型,里面有text, selection等属性。assert( value == null || !value.composing.isValid || value.isComposingRangeValid, 'New TextEditingValue $value ...' ) 是一个断言,如果不符合断言,就不会往下执行。其中:
- composing 表示正在编辑文本范围的TextRange对象,通常是输入法正在编辑的文本区域,这个区域的文本没有最终确定,通常是输入过程中正在编辑的内容。composing.isValid表示composing区域是否有效。
- isComposingRangeValid 用于检查composing的范围是否有效。判断 composing 区域的起始位置和结束位置是否在有效的范围内,是否没有错误地超出文本长度。
如果value是null 或者 composing无效 或composing的范围有效,就执行下一步的赋值操作。
由于TextEditingController是ValueNotifier的子类,在构造函数中,子类无法直接修改父类ValueNotifier的成员变量,所以需要通过super方法来调用父类的构造函数,来初始化继承自父类的成员变量。super(value ?? TextEditingValue.empty) 表示,如果外部传入的value值不是null,就以value赋值,如果value是null,就使用TextEditingValue的空值来赋值。
class TextEditingController extends ValueNotifier<TextEditingValue> {
/// ... 省略代码
String get text => value.text;
set text(String newText) {
value = value.copyWith(
text: newText,
selection: const TextSelection.collapsed(offset: -1),
composing: TextRange.empty,
);
}
set value(TextEditingValue newValue) {
assert(
!newValue.composing.isValid || newValue.isComposingRangeValid,
'New TextEditingValue $newValue has an invalid non-empty composing range '
'${newValue.composing}. It is recommended to use a valid composing range, '
'even for readonly text fields.',
);
super.value = newValue;
}
}
- String get text => value.text : 通过get 关键字,给 text提供了一个只读的访问方式,使外部能直接读取text值,而无法直接修改它。text 实际上是 TextEditingController 内部 value.text 的一个访问器。
- set text(String newText) : set关键字和get不一样,set 用于修改属性的值。使用 set 可以控制对 text 的修改。直接修改 value.text 会绕过一些重要的逻辑,比如清空选择、更新组合区域等。而使用 set 让开发者通过控制器来修改文本,确保这些重要的操作能够正确执行。set text 会触发 notifyListeners(),从而通知所有监听器,更新文本后 UI 会正确刷新。
- value是TextEditingValue类型,该类型有一个copyWith 方法,copyWith内部通过merge方法合并新旧value的值并将新的value值返回。value = value.copyWith(xxx)表示使用外部传入的value合并内部的value,返回一个新的value。
- set value 上方有@override,表示重写这个方法,因为value是ValueNotifier父类的值,TextEditingController 这个子类要重写父类的方法。因为子类不能直接修改父类的成员属性值,所以借助super来修改,super.value = newValue。
class TextEditingController extends ValueNotifier<TextEditingValue> {
/// ... 省略代码
TextSpan buildTextSpan({required BuildContext context, TextStyle? style , required bool withComposing}) {
assert(!value.composing.isValid || !withComposing || value.isComposingRangeValid);
final bool composingRegionOutOfRange = !value.isComposingRangeValid || !withComposing;
if (composingRegionOutOfRange) {
return TextSpan(style: style, text: text);
}
final TextStyle composingStyle = style?.merge(const TextStyle(decoration: TextDecoration.underline))
?? const TextStyle(decoration: TextDecoration.underline);
return TextSpan(
style: style,
children: <TextSpan>[
TextSpan(text: value.composing.textBefore(value.text)),
TextSpan(
style: composingStyle,
text: value.composing.textInside(value.text),
),
TextSpan(text: value.composing.textAfter(value.text)),
],
);
}
}
这一段是用来绘制输入过程中,正在编辑中的内容显示什么样式,比如:输入拼音过程中,拼音下方是否出现下划线、’ 等。
class TextEditingController extends ValueNotifier<TextEditingValue> {
/// ... 省略代码
TextSelection get selection => value.selection;
set selection(TextSelection newSelection) {
if (text.length < newSelection.end || text.length < newSelection.start) {
throw FlutterError('invalid text selection: $newSelection');
}
final TextRange newComposing = _isSelectionWithinComposingRange(newSelection) ? value.composing : TextRange.empty;
value = value.copyWith(selection: newSelection, composing: newComposing);
}
bool _isSelectionWithinComposingRange(TextSelection selection) {
return selection.start >= value.composing.start && selection.end <= value.composing.end;
}
}
- selection : 表示选择的范围,选中了那些文字,文字在哪些下标范围,如果selection的起始点和终点下标是相同的,是“折叠”状态,说明没有选中文本。get selection 只读。set selection修改。
- _isSelectionWithinComposingRange:检查当前文本选择(selection)是否位于组合区域(composing range)内。这个方法的作用是帮助验证用户选择的文本范围是否在正在被编辑或输入的区域内。
class TextEditingController extends ValueNotifier<TextEditingValue> {
/// ... 省略代码
void clear() {
value = const TextEditingValue(selection: TextSelection.collapsed(offset: 0));
}
void clearComposing() {
value = value.copyWith(composing: TextRange.empty);
}
}
1.clear: 清除value值以及“折叠”selection的起点和重点为0,重置状态。
2.clearComposing: 清除正在编辑中的文字。
更多推荐
所有评论(0)