LoginSignup
3
1

More than 1 year has passed since last update.

【Flutterレイアウト】Overlayの使用

Last updated at Posted at 2022-05-27

Flutterレイアウトシリーズのその他の記事

Overlayとは、言葉の通り、Widgetの上に被せるウェジェット部品とのことです。代表的なウェジェットはTooltipです。この記事はOverlayを使用、理解するため書いたものです。

※本記事は下記のZenn本にまとめました。

レンダリング(rendering)

Overlayを使用するには、Widgetのサイズ、offsetの値が必要です。そこで、contextのfindRenderObject()メソッドからrenderingを取得することが可能です。

RenderObject? renderObject = context.findRenderObject();
if (renderObject != null && renderObject is RenderBox) {
  print(renderObject.size);
  print(renderObject.localToGlobal(Offset.zero));
}

BuildContextの取得

UIツリーのScaffoldなど親ウェジェットを使うとき、contextは一番上層であるScaffoldのものが多いですが、ウェジェットを分離して、子ウェジェットのcontextを取得することも可能ですが、Builderウェジェットを使い、各自のContextを取得することも可能です。
例:

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('HomePage'),
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text("テキスト"),
            Builder(
              builder: (BuildContext ctx) => GestureDetector(
                onTap: () {
                  printInfo(ctx);
                },
                child: Container(
                  padding: const EdgeInsets.all(3),
                  child: const Text(
                    "context",
                    style: TextStyle(color: Colors.red),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void printInfo(BuildContext context) {
    RenderObject? renderObject = context.findRenderObject();
    if (renderObject != null && renderObject is RenderBox) {
      print(renderObject.size);
      print(renderObject.localToGlobal(Offset.zero));
    }
  }

Overlayの使用

上記の方法でoffsetを取得し、OverlayStateにOverlayEntryを追加することができます。Overlayの作成は下記の流れです。

  • OverlayStateの取得
final OverlayState? overlayState = Overlay.of(context);
  • OverlayEntryの作成
// offset
Offset targetOffset = Offset.zero;
RenderObject? renderObject = context.findRenderObject();
if (renderObject != null && renderObject is RenderBox) {
  targetOffset = renderObject.localToGlobal(Offset.zero);
}
final OverlayState? overlayState = Overlay.of(context);
if (overlayState == null) return;
// OverlayEntryの作成
OverlayEntry entry = OverlayEntry(
  builder: (BuildContext context) => Positioned(
       width: 50,
       height: 50,
       left: targetOffset.dx,
       top: targetOffset.dy,
       child: GestureDetector(
          onTap: removeEntry,
          child: const ColoredBox(
          color: Colors.red,
        ),
     ),
  ),
);
  • OverlayEntryのinsert
overlayState.insert(entry);
  • Overlayの取り消し
  void removeEntry() {
    if (_entry != null) {
      _entry!.remove();
      _entry = null;
    }
  }
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1