Flutter浮动视图插件flutter_portal的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter浮动视图插件flutter_portal的使用

Flutter中的flutter_portal插件提供了一种声明式的方法来创建和管理浮动视图,如工具提示、上下文菜单、对话框等。它改进了Flutter内置的Overlay/OverlayEntry机制,使其更加直观、易于对齐,并且可以更好地与Flutter的声明式UI模型结合使用。

🚀 优点

  • 声明式而非命令式:像Flutter中的其他所有内容一样,覆盖层(portals)现在是声明式的。只需将浮动UI作为普通小部件放入小部件树中。
  • 轻松对齐:内建支持将覆盖层相对于UI组件对齐。
  • 直观的Context:覆盖层条目构建时使用其直观的父级作为context

此外,还有以下优点:

  • 易于恢复属性:由于显示覆盖层就像调用setState一样简单,因此RestorableProperty可以很好地工作。
  • 正确的Theme/provider:覆盖层条目可以访问与显示覆盖层的小部件相同的Theme和不同的providers。

👀 示例代码

PortalTarget(
  // 声明式:只需提供`portalFollower`作为普通小部件
  portalFollower: MyAwesomeOverlayWidget(),
  // 对齐“跟随者”相对于“子项”
  anchor: Aligned.center,
  child: MyChildWidget(),
)

🪜 示例

查看示例文件夹了解如何使用flutter_portal

🧭 使用方法

  1. 安装插件。遵循标准安装此包的程序。最简单的方法可能是flutter pub add flutter_portal
  2. 添加Portal小部件。例如,将其放置在MaterialApp之上。每个应用程序只需要一个Portal
  3. 在需要显示覆盖层的地方使用PortalTarget

📚 教程:显示上下文菜单

添加Portal小部件

Portal(
  child: MaterialApp(...)
)

创建按钮

class MenuExample extends StatefulWidget {
  @override
  _MenuExampleState createState() => _MenuExampleState();
}

class _MenuExampleState extends State<MenuExample> {
  bool isMenuOpen = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: PortalTarget(
          visible: isMenuOpen,
          anchor: const Aligned(
            follower: Alignment.topLeft,
            target: Alignment.topRight,
          ),
          portalFollower: GestureDetector(
            behavior: HitTestBehavior.opaque,
            onTap: () {
              setState(() {
                isMenuOpen = false;
              });
            },
            child: Material(
              elevation: 8,
              child: IntrinsicWidth(
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    ListTile(title: Text('option 1')),
                    ListTile(title: Text('option 2')),
                  ],
                ),
              ),
            ),
          ),
          child: ElevatedButton(
            onPressed: () {
              setState(() {
                isMenuOpen = true;
              });
            },
            child: Text('show menu'),
          ),
        ),
      ),
    );
  }
}

完整示例

import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart';

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

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

class MenuExample extends StatefulWidget {
  @override
  _MenuExampleState createState() => _MenuExampleState();
}

class _MenuExampleState extends State<MenuExample> {
  bool isMenuOpen = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Flutter Portal Example')),
      body: Center(
        child: PortalTarget(
          visible: isMenuOpen,
          anchor: const Aligned(
            follower: Alignment.topLeft,
            target: Alignment.topRight,
          ),
          portalFollower: GestureDetector(
            behavior: HitTestBehavior.opaque,
            onTap: () {
              setState(() {
                isMenuOpen = false;
              });
            },
            child: Material(
              elevation: 8,
              child: IntrinsicWidth(
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    ListTile(title: Text('Option 1'), onTap: () {}),
                    ListTile(title: Text('Option 2'), onTap: () {}),
                  ],
                ),
              ),
            ),
          ),
          child: ElevatedButton(
            onPressed: () {
              setState(() {
                isMenuOpen = true;
              });
            },
            child: Text('Show Menu'),
          ),
        ),
      ),
    );
  }
}

通过以上步骤,您可以轻松地在Flutter应用中实现上下文菜单或其他类型的浮动视图。希望这个教程能帮助您更好地理解和使用flutter_portal插件。


更多关于Flutter浮动视图插件flutter_portal的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter浮动视图插件flutter_portal的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用flutter_portal插件来创建浮动视图的示例代码。flutter_portal插件允许你在Flutter应用中创建浮动的内容,这些内容可以覆盖在其他UI元素之上。

首先,确保你的pubspec.yaml文件中已经添加了flutter_portal依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_portal: ^0.15.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

示例代码

下面是一个简单的示例,展示如何使用flutter_portal来创建一个浮动按钮,该按钮可以覆盖在页面的其他内容之上。

1. 创建主页面(Main Page)

import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'overlay_content.dart';  // 导入浮动内容

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: PortalHost(
        child: Scaffold(
          appBar: AppBar(
            title: Text('Flutter Portal Example'),
          ),
          body: Center(
            child: Text('This is the main content.'),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {},
            tooltip: 'Open Overlay',
            child: Icon(Icons.add),
          ),
        ),
        portal: OverlayContent(),  // 浮动内容
      ),
    );
  }
}

2. 创建浮动内容(Overlay Content)

overlay_content.dart文件中,定义浮动内容:

import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart';

class OverlayContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return PortalEntry(
      visible: true,  // 控制浮动内容的显示与隐藏
      child: Material(
        elevation: 8.0,  // 设置阴影
        child: Container(
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(10.0),
          ),
          padding: EdgeInsets.all(16.0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text('This is the overlay content.'),
              SizedBox(height: 16.0),
              ElevatedButton(
                onPressed: () {
                  // 可以在这里添加关闭浮动内容的逻辑
                },
                child: Text('Close'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

解释

  1. PortalHost:这是flutter_portal提供的一个Widget,用于作为浮动内容的容器。它有一个child属性,用于显示正常的内容,还有一个portal属性,用于显示浮动的内容。

  2. PortalEntry:这是浮动内容的入口点,visible属性用于控制浮动内容的显示与隐藏。child属性是实际的浮动内容。

  3. 浮动内容:在OverlayContent类中,我们创建了一个简单的浮动内容,包括一些文本和一个关闭按钮。

运行代码

将上述代码放入你的Flutter项目中,然后运行应用。你应该会看到一个带有浮动按钮的主页面,当你点击浮动按钮时(尽管这个例子中未添加打开浮动内容的逻辑),你可以手动在PortalHostportal属性中显示浮动内容。

你可以根据需要进一步扩展这个示例,比如添加打开浮动内容的逻辑,或者在浮动内容中添加更多的交互元素。

回到顶部