RenderEditable
需要在進行點擊測試前先佈局
摘要
#RenderEditable
的實例必須在處理點擊測試之前進行佈局。在佈局之前嘗試對 RenderEditable
物件進行點擊測試會導致斷言錯誤,例如以下所示:
Failed assertion: line 123 pos 45: '!debugNeedsLayout': is not true.
背景
#為了支援可選取文字中的手勢辨識器,RenderEditable
需要其文字跨度的佈局資訊,以確定哪個文字跨度接收了指標事件。(在此變更之前,RenderEditable
物件在評估點擊測試時不會將其文字納入考量。)為了實現這一點,佈局成為對 RenderEditable
物件執行點擊測試的先決條件。
實際上,這很少成為問題。小部件庫確保在對所有渲染物件進行任何點擊測試之前都執行佈局。這個問題只可能出現在直接與渲染物件互動的程式碼中,例如在自定義渲染物件的測試中。
遷移指南
#如果您在點擊測試 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 文件
相關問題
- Issue 43494: SelectableText.rich 與 TapGestureRecognizer 一起使用時無法運作
相關 PR
除非另有說明,否則本網站上的文件反映了 Flutter 的最新穩定版本。頁面上次更新時間為 2024-04-04。 檢視原始碼 或 回報問題。