<

RenderEditable はヒット テストの前にレイアウトする必要があります

まとめ

のインスタンスRenderEditable処理がヒットする前にレイアウトする必要があります テスト中。ヒットテストを試みていますRenderEditableレイアウト前のオブジェクト 結果は次のようなアサーションになります。

Failed assertion: line 123 pos 45: '!debugNeedsLayout': is not true.

コンテクスト

選択可能なテキストでジェスチャ認識機能をサポートするには、RenderEditableにはレイアウト情報が必要です テキスト スパンを使用して、どのテキスト スパンが ポインタイベント。 (変更前は、RenderEditableオブジェクト ヒット テストを評価する際にテキストは考慮されませんでした。) これを実装するために、レイアウトが実行の前提条件になりました。 でのヒットテストRenderEditable物体。

実際には、これが問題になることはほとんどありません。ウィジェットライブラリ すべてのヒット テストの前にレイアウトが実行されるようにします。 オブジェクトをレンダリングします。この問題は次の地域でのみ発生する可能性があります。 レンダリング オブジェクトと直接対話するコード。 カスタム レンダー オブジェクトのテストの例。

移行ガイド

を見た場合は、'!debugNeedsLayout': is not trueヒットテスト中のアサーションエラーRenderEditable、 レイアウトするRenderEditableそうする前に。

移行前のコード:

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) {}
}

移行後のコード:

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 ドキュメント:

  • RenderEditable

関連する問題:

  • 問題 43494: SelectableText.rich と一緒に使用されます TapGestureRecognizer が動作しない

関連する PR:

  • PR 54479:選択可​​能なリッチ テキストでジェスチャ認識機能を有効にする