Flutter Overlay 你用上了么

<img src="https://ducafecat.oss-cn-beijing.aliyuncs.com/podcast/2023/05/019d70aac9f69a63abd4fb93d169de05.jpeg" alt="Flutter overlay did you use it?" style="width:90%;" />

前言

Flutter中的Overlay是一个用于在屏幕上显示浮层的组件。它能够用来在应用程序中创立弹出窗口、提示框、菜单、对话框等等。

Overlay通常用于在用户与应用程序交互时显示临时性的UI元素,例如:用户点击按钮时显示下拉菜单、用户长按屏幕时显示上下文菜单、显示正告或谬误音讯等等。

Overlay通常蕴含一个Stack布局,每个浮层都是一个Positioned widget,能够增加到Stack中。这样,能够将多个浮层叠加在一起,并管制它们的档次关系。

Flutter中的Overlay能够让开发者轻松创立简单的UI,同时还能够放弃应用程序的性能和响应度。

本文中提供的代码示例演示了如何在Flutter中应用Overlay制作工作覆盖层。Overlay包含两个根本组件:OverlayState和OverlayEntry。OverlayState治理所有OverlayEntry,OverlayEntry定义覆盖层中的内容。在示例中,OverlayEntry蕴含一个带有文本和色彩的容器,能够在屏幕上显示。这些条目能够通过OverlayState的insert和remove办法增加和删除。

原文 https://ducafecat.com/blog/flutter-overlay-did-you-use-it

<img src="https://ducafecat.oss-cn-beijing.aliyuncs.com/podcast/2023/05/15894a6d156e574b80aa96dc62a13740.png" alt="image-20230518102503338" style="width:50%;" />

视频

https://www.bilibili.com/video/BV1qX4y1C7rb/

代码

https://github.com/ducafecat/flutter_develop_tips/tree/main/flutter_application_overlay

参考

https://api.flutter.dev/flutter/widgets/Overlay-class.html

https://api.flutter.dev/flutter/widgets/OverlayEntry-class.html

OverlayEntry

Overlay 通过将独立的子窗口小部件插入到重叠的堆栈中,使它们在其余窗口小部件之上“浮动”可视元素。笼罩容许每个小部件应用 OverlayEntry 对象治理它们在笼罩中的参加。

构造函数

OverlayEntry({  required this.builder,  bool opaque = false,  bool maintainState = false,})
  • builder:此属性用于此条目,并将在条目地位的笼罩中蕴含此构建器构建的小部件。
  • opaque:此属性用于获取bool值,该值决定此条目是否阻止整个笼罩。如果条目申明为不通明,则为了提高效率,除非它们具备maintainState设置,否则笼罩将跳过在该条目上面构建条目。
  • maintainState:如果您须要在OverlayEntry中应用有状态的小部件,那么您须要将maintainState设置为true,以便小部件能够放弃其状态并接管生命周期办法。如果您只是在OverlayEntry中显示一个动态小部件,则能够将maintainState设置为false,以便小部件能够开释内存和资源,不会对性能产生过多影响。

OverlayEntry办法

只有一个OverlayEntry的办法

  • remove:此办法用于从覆盖层中删除此条目

OverlayState

Overlay的以后状态用于将OverlayEntries插入覆盖层中。

OverlayState办法

  • debugIsVisible:此办法用于查看给定的OverlayEntry是否可见,并返回布尔值。
  • insert:此办法用于将给定的OverlayEntry插入覆盖层中。
  • insertAll:此办法用于获取OverlayEntries的List,并将所有条目插入覆盖层中。您还能够指定上述和下述属性以阐明要插入条目标程序。
  • rearrange:它能够重新排列以后在屏幕上叠加的所有小部件。具体来说,rearrange办法会将最初增加的OverlayEntry小部件挪动到最下面,并将其余小部件挪动到上面。这能够用于确保最新的OverlayEntry始终位于最下面,并且能够接管用户的触摸事件等。

步骤

第一步:成员变量

  /// overlay 状态  OverlayState? overlayState;  /// overlay 层汇合  List<OverlayEntry> entriesList = [];
  @override  void initState() {    super.initState();    // 获取 overlay 状态    overlayState = Overlay.of(context);  }
  @override  void dispose() {    // 销毁    overlayState?.dispose();    super.dispose();  }

第二步:随机层显示

  // 随机地位显示层  void showRandomOverlay(BuildContext context) {    // 随机色彩    final bgColor = Color.fromARGB(      255,      1 + Random().nextInt(254),      1 + Random().nextInt(254),      1 + Random().nextInt(254),    );    // 屏幕宽度    final screenWidth = MediaQuery.of(context).size.width;    // 随机屏幕高度    final randomHeight =        MediaQuery.of(context).size.height * Random().nextDouble();    OverlayEntry? overlayEntry;    overlayEntry = OverlayEntry(builder: (context) {      return Positioned(        // 指定地位        left: 0,        top: randomHeight,        child: GestureDetector(          // 点击删除          onTap: () {            overlayEntry?.remove();            entriesList.remove(overlayEntry);          },          // 背景随机色          child: Container(            width: screenWidth,            height: 100,            color: bgColor,            child: Center(              // 提醒文字              child: Text(                "这是一个 overlay ${Random().nextInt(100)} 层, 点击敞开",                style: const TextStyle(                  color: Colors.white,                  fontSize: 20,                  decoration: TextDecoration.none,                ),              ),            ),          ),        ),      );    });    overlayState?.insert(overlayEntry);    entriesList.add(overlayEntry);  }

第三步:管制按钮

  // 管制按钮  Widget _buildBtns() {    return Row(      mainAxisAlignment: MainAxisAlignment.spaceEvenly,      children: [        // 随机新增        ElevatedButton(          onPressed: () => showRandomOverlay(context),          child: const Text("随机新增"),        ),        // 敞开所有        ElevatedButton(          onPressed: () {            for (final entry in entriesList) {              entry.remove();            }            entriesList = [];          },          child: const Text("敞开所有"),        ),        // 随机排序        ElevatedButton(          onPressed: () {            // 从屏幕上移除            for (final entry in entriesList) {              entry.remove();            }            // 应用Random类创立随机数生成器            Random random = Random();            // 应用List的sublist()办法创立一个新列表            List<OverlayEntry> shuffledEntries = entriesList.sublist(0);            // 调用List的shuffle()办法,传入一个随机数生成器            shuffledEntries.shuffle(random);            // 插入界面            overlayState?.insertAll(shuffledEntries);          },          child: const Text("随机排序"),        ),      ],    );  }

最初:主视图显示

  // 主视图  Widget _mainView() {    return Padding(      padding: const EdgeInsets.only(top: 100),      child: Align(        alignment: Alignment.topCenter,        child: _buildBtns(),      ),    );  }
  @override  Widget build(BuildContext context) {    return Scaffold(      body: _mainView(),    );  }

残缺代码

lib/overlay_view.dart

import 'dart:math';import 'package:flutter/material.dart';class OverlayUsePage extends StatefulWidget {  const OverlayUsePage({super.key});  @override  State<OverlayUsePage> createState() => _OverlayUsePageState();}class _OverlayUsePageState extends State<OverlayUsePage> {  /// overlay 状态  OverlayState? overlayState;  /// overlay 层汇合  List<OverlayEntry> entriesList = [];  // 随机地位显示层  void showRandomOverlay(BuildContext context) {    // 随机色彩    final bgColor = Color.fromARGB(      255,      1 + Random().nextInt(254),      1 + Random().nextInt(254),      1 + Random().nextInt(254),    );    // 屏幕宽度    final screenWidth = MediaQuery.of(context).size.width;    // 随机屏幕高度    final randomHeight =        MediaQuery.of(context).size.height * Random().nextDouble();    OverlayEntry? overlayEntry;    overlayEntry = OverlayEntry(builder: (context) {      return Positioned(        // 指定地位        left: 0,        top: randomHeight,        child: GestureDetector(          // 点击删除          onTap: () {            overlayEntry?.remove();            entriesList.remove(overlayEntry);          },          // 背景随机色          child: Container(            width: screenWidth,            height: 100,            color: bgColor,            child: Center(              // 提醒文字              child: Text(                "这是一个 overlay ${Random().nextInt(100)} 层, 点击敞开",                style: const TextStyle(                  color: Colors.white,                  fontSize: 20,                  decoration: TextDecoration.none,                ),              ),            ),          ),        ),      );    });    overlayState?.insert(overlayEntry);    entriesList.add(overlayEntry);  }  // 管制按钮  Widget _buildBtns() {    return Row(      mainAxisAlignment: MainAxisAlignment.spaceEvenly,      children: [        // 随机新增        ElevatedButton(          onPressed: () => showRandomOverlay(context),          child: const Text("随机新增"),        ),        // 敞开所有        ElevatedButton(          onPressed: () {            for (final entry in entriesList) {              entry.remove();            }            entriesList = [];          },          child: const Text("敞开所有"),        ),        // 随机排序        ElevatedButton(          onPressed: () {            // 从屏幕上移除            for (final entry in entriesList) {              entry.remove();            }            // 应用Random类创立随机数生成器            Random random = Random();            // 应用List的sublist()办法创立一个新列表            List<OverlayEntry> shuffledEntries = entriesList.sublist(0);            // 调用List的shuffle()办法,传入一个随机数生成器            shuffledEntries.shuffle(random);            // 插入界面            overlayState?.insertAll(shuffledEntries);          },          child: const Text("随机排序"),        ),      ],    );  }  // 主视图  Widget _mainView() {    return Padding(      padding: const EdgeInsets.only(top: 100),      child: Align(        alignment: Alignment.topCenter,        child: _buildBtns(),      ),    );  }  @override  void initState() {    super.initState();    // 获取 overlay 状态    overlayState = Overlay.of(context);  }  @override  void dispose() {    // 销毁    overlayState?.dispose();    super.dispose();  }  @override  Widget build(BuildContext context) {    return Scaffold(      body: _mainView(),    );  }}

小结

本文提供了一个很好的介绍Flutter Overlay的概念和应用办法。无论是初学者还是有教训的开发人员,都能够从本文中取得新的常识和见解。如果你想在你的Flutter我的项目中实现工作覆盖层,本文是一个很好的终点。


© 猫哥
ducafecat.com

end

本文由mdnice多平台公布