在进行点击测试之前,需要布局 RenderEditable
摘要
#在处理点击测试之前,必须先布局 RenderEditable
实例。在布局之前尝试点击测试 RenderEditable
对象会导致断言错误,例如以下错误:
Failed assertion: line 123 pos 45: '!debugNeedsLayout': is not true.
上下文
#为了在可选择文本中支持手势识别器,RenderEditable
需要其文本跨度的布局信息来确定哪个文本跨度接收指针事件。(在此更改之前,RenderEditable
对象在评估点击测试时不会考虑其文本。)为了实现这一点,布局成为了对 RenderEditable
对象进行点击测试的先决条件。
在实践中,这很少成为问题。widget 库确保在所有渲染对象上的任何点击测试之前都执行布局。此问题仅可能出现在直接与渲染对象交互的代码中,例如自定义渲染对象的测试中。
迁移指南
#如果您在对 RenderEditable
进行点击测试时看到 '!debugNeedsLayout': is not true
断言错误,请在进行点击测试之前布局 RenderEditable
。
迁移前的代码
dart
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
void main() {
test('attach and detach correctly handle gesture', () {
final RenderEditable editable = RenderEditable(
textDirection: TextDirection.ltr,
offset: ViewportOffset.zero(),
textSelectionDelegate: FakeEditableTextState(),
startHandleLayerLink: LayerLink(),
endHandleLayerLink: LayerLink(),
);
final PipelineOwner owner = PipelineOwner(onNeedVisualUpdate: () {});
editable.attach(owner);
// This throws an assertion error because
// the RenderEditable hasn't been laid out.
editable.handleEvent(const PointerDownEvent(),
BoxHitTestEntry(editable, const Offset(10, 10)));
editable.detach();
});
}
class FakeEditableTextState extends TextSelectionDelegate {
@override
TextEditingValue textEditingValue;
@override
void hideToolbar() {}
@override
void bringIntoView(TextPosition position) {}
}
迁移后的代码
dart
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
void main() {
test('attach and detach correctly handle gesture', () {
final RenderEditable editable = RenderEditable(
textDirection: TextDirection.ltr,
offset: ViewportOffset.zero(),
textSelectionDelegate: FakeEditableTextState(),
startHandleLayerLink: LayerLink(),
endHandleLayerLink: LayerLink(),
);
// Lay out the RenderEditable first.
editable.layout(BoxConstraints.loose(const Size(1000.0, 1000.0)));
final PipelineOwner owner = PipelineOwner(onNeedVisualUpdate: () {});
editable.attach(owner);
editable.handleEvent(const PointerDownEvent(),
BoxHitTestEntry(editable, const Offset(10, 10)));
editable.detach();
});
}
class FakeEditableTextState extends TextSelectionDelegate {
@override
TextEditingValue textEditingValue;
@override
void hideToolbar() {}
@override
void bringIntoView(TextPosition position) {}
}
时间线
#包含于版本:1.18.0
稳定版发布:1.20
参考
#API 文档
相关问题
- 问题 43494:与 TapGestureRecognizer 一起使用的 SelectableText.rich 无法工作
相关 PR
除非另有说明,否则本网站上的文档反映了 Flutter 的最新稳定版本。页面最后更新于 2024-04-04。 查看源代码 或 报告问题。