Flutter悬浮UI的设计Overlay组件

简介: Flutter悬浮UI的设计Overlay组件

APP开发经常要遇到的开发场景

有时候我们在开发APP的时候会遇到下面这些需求:


在现有页面上添加浮动的悬浮按钮、气泡或菜单。

实现全局的通知或提示弹窗。

创建自定义的导航栏、底部导航或标签栏。

构建模态对话框或底部弹出菜单。

在屏幕上展示悬浮窗,比如 Flutter 版本的 Toast,任意位置的 PopWindow 等等。

自定义Toast。

在页面顶部悬浮某个widget。

等等。

这些场景都有一个共同特点,需要在当前UI上悬浮显示特定的UI。要用flutter来实现这些效果就要引出今天要学习的Overlay组件。

Overlay 的介绍

当需要在 Flutter 应用中在现有 UI 层上添加新的视图或交互时,可以使用 Overlay 组件。Overlay 允许将一个或多个小部件(称为 OverlayEntry)叠加在应用的现有 UI 上。

Overlay包括两个基本组件:OverlayState和OverlayEntry。OverlayState管理所有OverlayEntry,OverlayEntry定义覆盖层的内容。


Overlay的使用规则

创建一个 Overlay 对象,通常使用 Overlay.of(context) 方法获取当前上下文中的 Overlay 对象。

创建一个或多个 OverlayEntry 对象,这些对象将成为 Overlay 的子项。

将 OverlayEntry 添加到 Overlay 中,通常使用 OverlayEntry 的 insert 或 add 方法。

当需要显示或隐藏叠加层时,调用 OverlayEntry 的 markNeedsBuild 方法,并在 build 方法中定义要显示的小部件。

可选:通过调整 OverlayEntry 的位置、大小和布局参数来控制叠加层的位置和样式。

举例说明

下面通过一个简单的例子来说明:例子要实现点击一个按钮会打开Overlay显示一个FloatingActionButton。


源码

import 'package:flutter/material.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Overlay Example'),
        ),
        body: Center(
          child: ElevatedButton(
            child: Text('Open Overlay'),
            onPressed: () {
              showFloatingButtonOverlay(context);
            },
          ),
        ),
      ),
    );
  }
}
void showFloatingButtonOverlay(BuildContext context) {
  OverlayState? overlayState = Overlay.of(context);
  late OverlayEntry overlayEntry;
  // 创建 OverlayEntry
  overlayEntry = OverlayEntry(
    builder: (BuildContext context) {
      return Positioned(
        top: 100,
        right: 16,
        child: FloatingActionButton(
          onPressed: () {
            // 悬浮按钮被点击
            print('Floating Button Clicked');
            overlayEntry.remove(); // 移除 OverlayEntry
          },
          child: Icon(Icons.add),
        ),
      );
    },
  );
  // 将 OverlayEntry 添加到 Overlay 中
  overlayState?.insert(overlayEntry);
}

运行结果如图:


例子报错

本来想直接贴正确的代码的,但是觉得这个错误对初学者来说很容易犯,故单独列出来。


报错No Overlay widget found

点击Open Overlay按钮报错No Overlay widget found。如下图



报错原因

该错误提示是因为在使用 Overlay.of(context) 方法时,找不到可用的 Overlay 对象。


解决方法

确保按钮所在的 BuildContext 对象正确。在上述示例中,按钮的 onPressed 回调中使用的 BuildContext 应该是 Scaffold 的上下文,确保按钮在正确的上下文中定义和使用。


确保 Overlay 被正确地放置在应用的组件树中。在上述示例中,Overlay 组件应该在 MaterialApp 或 WidgetsApp 的下方,以确保它们在正确的层次结构中。


修改后的源码

import 'package:flutter/material.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: OverlayExample(), // 使用 OverlayExample 作为主页
    );
  }
}
class OverlayExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Overlay Example'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Open Overlay'),
          onPressed: () {
            showFloatingButtonOverlay(context);
          },
        ),
      ),
    );
  }
}
void showFloatingButtonOverlay(BuildContext context) {
  OverlayState? overlayState = Overlay.of(context);
  late OverlayEntry overlayEntry;
  // 创建 OverlayEntry
  overlayEntry = OverlayEntry(
    builder: (BuildContext context) {
      return Positioned(
        top: 100,
        right: 16,
        child: FloatingActionButton(
          onPressed: () {
            // 悬浮按钮被点击
            print('Floating Button Clicked');
            overlayEntry.remove(); // 移除 OverlayEntry
          },
          child: Icon(Icons.add),
        ),
      );
    },
  );
  // 将 OverlayEntry 添加到 Overlay 中
  overlayState?.insert(overlayEntry);
}

例子效果

运行起来的效果如图:

88fa00388daab9c56e93cfe76196209a.png

点击Open Overlay按钮后的效果图如下:


相关文章
|
23天前
|
缓存 搜索推荐 索引
「Mac畅玩鸿蒙与硬件12」鸿蒙UI组件篇2 - Image组件的使用
在鸿蒙应用开发中,Image 组件用于加载和显示图片资源,并提供多种属性来控制图片的显示效果和适配方式。本篇将带你学习如何在鸿蒙应用中加载本地和远程图片、设置图片样式以及实现简单的图片轮播功能。
87 7
「Mac畅玩鸿蒙与硬件12」鸿蒙UI组件篇2 - Image组件的使用
|
14天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
9天前
|
搜索推荐 前端开发 开发者
「Mac畅玩鸿蒙与硬件19」鸿蒙UI组件篇9 - 自定义动画实现
自定义动画让开发者可以设计更加个性化和复杂的动画效果,适合表现独特的界面元素。鸿蒙提供了丰富的工具,支持通过自定义路径和时间控制来创建复杂的动画运动。本篇将带你学习如何通过自定义动画实现更多样化的效果。
63 11
「Mac畅玩鸿蒙与硬件19」鸿蒙UI组件篇9 - 自定义动画实现
|
9天前
|
UED
「Mac畅玩鸿蒙与硬件17」鸿蒙UI组件篇7 - Animation 组件基础
在应用开发中,动画效果可以增强用户体验。鸿蒙框架提供了 translate、scale 和 rotate 等动画功能,允许对组件进行平移、缩放和旋转等操作。本篇将介绍 Animation 组件的基础知识和示例代码。
60 10
「Mac畅玩鸿蒙与硬件17」鸿蒙UI组件篇7 - Animation 组件基础
|
7天前
|
前端开发 开发者
「Mac畅玩鸿蒙与硬件22」鸿蒙UI组件篇12 - Canvas 组件的动态进阶应用
在鸿蒙应用中,Canvas 组件可以实现丰富的动态效果,适合用于动画和实时更新的场景。本篇将介绍如何在 Canvas 中实现动画循环、动态进度条、旋转和缩放动画,以及性能优化策略。
36 6
「Mac畅玩鸿蒙与硬件22」鸿蒙UI组件篇12 - Canvas 组件的动态进阶应用
|
7天前
|
前端开发 开发者
「Mac畅玩鸿蒙与硬件23」鸿蒙UI组件篇13 - 自定义组件的创建与使用
自定义组件可以帮助开发者实现复用性强、逻辑清晰的界面模块。通过自定义组件,鸿蒙应用能够提高代码的可维护性,并简化复杂布局的构建。本篇将介绍如何创建自定义组件,如何向组件传递数据,以及如何在不同页面间复用这些组件。
29 5
「Mac畅玩鸿蒙与硬件23」鸿蒙UI组件篇13 - 自定义组件的创建与使用
|
10天前
|
存储 数据安全/隐私保护 开发者
「Mac畅玩鸿蒙与硬件13」鸿蒙UI组件篇3 - TextInput 组件获取用户输入
在鸿蒙应用开发中,TextInput 组件用于接收用户输入,适用于文本、密码等多种输入类型。本文详细介绍鸿蒙 TextInput 组件的使用方法,包括输入限制、样式设置、事件监听及搜索框应用,帮助你灵活处理鸿蒙应用中的用户输入。
45 7
「Mac畅玩鸿蒙与硬件13」鸿蒙UI组件篇3 - TextInput 组件获取用户输入
|
25天前
|
自然语言处理 开发者
「Mac畅玩鸿蒙与硬件11」鸿蒙 UI 组件篇1 - Text 和 Button 组件详解
本篇将详细介绍鸿蒙应用开发中的 Text 和 Button 组件。通过本篇内容,你将学习如何使用 Text 组件显示文本、格式化文本样式,以及如何使用 Button 组件处理点击事件并自定义样式。掌握这些基本组件的用法将为后续的 UI 开发奠定基础。
101 4
「Mac畅玩鸿蒙与硬件11」鸿蒙 UI 组件篇1 - Text 和 Button 组件详解
|
28天前
Flutter 自定义组件继承与调用的高级使用方式
本文深入探讨了 Flutter 中自定义组件的高级使用方式,包括创建基本自定义组件、继承现有组件、使用 Mixins 和组合模式等。通过这些方法,您可以构建灵活、可重用且易于维护的 UI 组件,从而提升开发效率和代码质量。
123 1
|
28天前
|
开发工具 UED
Flutter&鸿蒙next中封装一个输入框组件
本文介绍了如何创建一个简单的Flutter播客应用。首先,通过`flutter create`命令创建项目;接着,在`lib`目录下封装一个自定义输入框组件`CustomInput`;然后,在主应用文件`main.dart`中使用该输入框组件,实现简单的UI布局和功能;最后,通过`flutter run`启动应用。本文还提供了后续扩展建议,如状态管理、网络请求和UI优化。
100 1