在flutter中创建一个全局浮动按钮

Creating a global floating button in flutter

是否可以在所有页面顶部的应用程序的整个生命周期中显示浮动按钮?我知道 Scaffold 我可以拥有它,但它只适用于那个页面,一旦我在导航器堆栈上推送一个新页面,我就会失去它。

是的,OverlayEntry就是为此目的而制作的。

要插入它,您可以这样做:

ElevatedButton(
  child: Text("Overlay Test"),
  onPressed: () {
    final entry = OverlayEntry(
      builder: (context) => Container(
        color: Colors.blue,
      ),
    );
    Overlay.of(context)?.insert(entry);
  },
)

如果以后要删除它,可以保存 entry 变量,然后在需要时调用 entry.remove()

完整示例:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  OverlayEntry? _entry;
  double _left = 50;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("OverlayEntry Demo"),
      ),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ElevatedButton(
              child: Text("Add OverlayEntry"),
              onPressed: () {
                _entry = OverlayEntry(
                  builder: (context) {
                    print("build");
                    return Positioned(
                      left: _left,
                      top: 200,
                      child: Container(
                        width: 150,
                        height: 150,
                        color: Colors.grey,
                      ),
                    );
                  },
                );
                Overlay.of(context)?.insert(_entry!);
              },
            ),
            ElevatedButton(
              child: Text("Move it"),
              onPressed: () {
                _left += 10;
                _entry?.markNeedsBuild();
              },
            ),
            ElevatedButton(
              child: Text("Remove it"),
              onPressed: () => _entry?.remove(),
            ),
          ],
        ),
      ),
    );
  }
}

一个选项是使用 MaterialAppbuilder 创建一个 Stack 并将您的按钮置于顶部:

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Test',
      home: TestPage(),
      initialRoute: "/test",
      builder: (context, child) {
        return Scaffold(
          body: Stack(
            children: [
              child!,
              Positioned(
                    left: 0,
                    bottom: 0,
                    child: **your button here**,
              ),
            ],
          ),
        );
      },
      routes: routes(context),
    );
  }
}