Flutter TolyUI 框架#02 | Popover 与 Tooltip 设计

本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!


《Flutter TolyUI 框架》系列前言:

TolyUI张风捷特烈 打造的 Fluter 全平台应用开发 UI 框架。具备 全平台组件化源码开放响应式 四大特点。可以帮助开发者迅速构建具有响应式全平台应用软件:

开源地址: github.com/TolyFx/toly...

该系列将详细介绍 TolyUI 框架使用方式、框架开发过程中的技术知识、设计理念、难题解决等。本篇将介绍 TolyUI 反馈模块 中的两个重要组件,它们的视图职能如下视频所示:


一、Tooltip 的再设计

TolyUI 框架中组件的设计原则之一是:

不轻易增加组件,每个 TolyUI 中被设计的组件,都应有它的设计动机。

组件的设计动机包括:

  • [1]. 提供 Flutter 中不存在的常用交互组件。
  • [2]. 对于 Flutter 已有但支持比较弱的组件, TolyUI 将基于源码,进行改造,以此拓展功能。

1.Tooltip 设计动机

Flutter 虽然内置了 Tooltip 组件,但它只能进行简单展示提示信息,效果如下:

这种视觉效果并不能满足通用场景:比如提示框的对齐方式,或者气泡包裹自适应边界灵活自定义内容 等。这就是Tooltip 在 TolyUI 中再设计动机,如下通过 TolyTooltip 组件达到的效果:


2. tolyui_feedback 模块

TolyUI 的模块化,将相对独立的功能 单独分包 。功能上 Tooltip 在一个组件基础上,展开提示信息。属于一种交互的反馈,反馈内容是静态信息,不参与交互。反馈相关的组件将分离 【tolyui_feedback】 包提供功能:

同样,使用者可以 tolyui_feedback 独立模块包,或者使用 tolyui 全家桶来享用 TolyTooltip 组件。

yaml 复制代码
# 仅使用反馈模块 
dependencies: 
   tolyui_feedback: ^last_version

# 使用 tolyui 全家桶 
dependencies: 
    tolyui: ^last_version

3. TolyTooltip 的功能

Tooltip在的设计语义是: 具有辅助反馈的功能 提示浮层。它会在目标组件 child 为基础,弹出用于展示的文字浮窗。这种浮窗是非侵扰性,一般不会响应事件,也不会消费目标组件的点击事件。在鼠标悬浮/手势长按事件中动画展开浮层。

有道 飞书
  • [1]. 动画展示/隐藏浮层弹框。
  • [2]. 支持 12 种弹框与目标组件的对齐方式。
  • [3]. 支持气泡框和非气泡框,填充与边模式线的弹框。
  • [4]. 支持边界溢出检测,并自动适应偏移功能。

二 、TolyTooltip 用法

对于桌面端和 web 平台来说,悬浮展示提示信息是一个非常常用的功能。下面介绍一下 TolyTooltip 的用法,感受一下它所带来的便利性和强大功能。

TolyTooltip 的使用案例介绍可以网站访问 TolyUI 的 web 版 Flutter 应用。

组件/反馈组件/popover: toly1994.com/ui/#/widget...


1. 浮窗的对齐方式

如下所示,TolyTooltip 提供了 12 种浮窗对齐方式,分为上下左右四组,每组有三种对齐方式。另外,默认提示框 支持气泡框,而且气泡的尖角位置会随着对其方式发生变化:

使用方式非常简单,直接通过 TolyTooltip 组件嵌套在目标组件之上即可。其中:

  • textStyle 参数可以指定浮窗内文字样式。
  • padding 参数设置浮层弹框内边距。
  • placement 参数设置浮层弹框和目标组件的对其方式。
  • gap 参数设置浮层弹框和目标组件的距离。
  • message 参数设置浮层弹框文字内容。
dart 复制代码
TolyTooltip(
  textStyle: TextStyle(fontSize: 13,color: Colors.white),
  padding: EdgeInsets.symmetric(horizontal: 12,vertical: 8),
  placement: TooltipPlacement.bottom,
  gap: 12,
  message: /// 提示信息,
  child: ///目标组件
),

提示框摆放的位置,通过 TooltipPlacement 枚举表示。有如下 12 种:

dart 复制代码
enum TooltipPlacement {
  top,
  topStart,
  topEnd,
  bottom,
  bottomStart,
  bottomEnd,
  left,
  leftStart,
  leftEnd,
  right,
  rightStart,
  rightEnd
}

2. 展示富文本

可以通过 richText 参数设置 InlineSpan 可以展示富文本。包括使用 WidgetSpan 在文字中嵌入组件。效果如下: :如果不知道 InlineSpan 是什么,可以阅读 《RichText》 组件的相关文章。

dart 复制代码
const InlineSpan span = TextSpan(children: [
  TextSpan(text: '请通过此邮箱联系我们\n '),
  TextSpan(
    style: TextStyle(color: Colors.blue),
    text: '1981462002@qq.com ',
  )
]);

TolyTooltip(
  richMessage: span,
  placement: TooltipPlacement.top,
  padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
  gap: 12,
  child: ///目标组件
);

3. 边界溢出自适应

边界溢出检测,并自动适应偏移功能,是花费我很大心力实现的。相比于绝对遵从对其方式而是提示框溢出边界,只能展示一部分,边界溢出自适应更加合理。如下所示:

  • Flutter 介绍 按钮的 Tooltip 对齐方式设置为 top,但当上方展示的区域不足时,自动转换为 bottom。
  • TolyUI 链接对齐方式设置为 left ,当上方展示的区域不足时,自动转换为 leftStart。

4. 样式设置

TolyTooltip 提供了很多可配置的选项,比如背景色、填充模式等,让使用者可以更灵活地展示信息。另外通过设置最大高度,可以在弹框高度过高时允许滑动。效果如下:

上面的第一个案例是取消气泡框效果: 将 decorationConfig 参数的 isBubble 置为 false 即可。另外,该配置参数中还可以设置背景色、填充模式、文字颜色:

dart 复制代码
  Widget buildTooltipDisplay1(){
    String message = '...';
    return TolyTooltip(
      message: message,
      placement: TooltipPlacement.top,
      textStyle: const TextStyle(fontFamily: '宋体',fontSize: 12,fontWeight: FontWeight.bold),
      decorationConfig: const DecorationConfig(
        isBubble: false,
        textColor: Colors.white,
      ),
      maxWidth: 250,
      padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
      gap: 12,
      child: const TolyLink(
        text: '张风捷特烈', href: 'https://juejin.cn/user/149189281194766', onTap: jumpUrl,
      ),
    );
  }

三、Popover 的设计动机

当点击组件时,有时需要打开一个浮层弹框,并且在面板中进行交互。虽然 PopMenuButton 等组件可以展开浮层菜单栏,但是一方面浮层弹框的自定义灵活性很差,另一方面,仅展示一个浮层面板,并不是很符合菜单的语义。

比如下面微信和飞书中展开的面板,严格意义上来说不能称之为 菜单,但也不是提示信息。这就是 Popover 的设计动机:

通过交互,展开一个 支持交互 的浮层面板,并允许外界控制展示和隐藏

微信头像点击 飞书文档

可能有人会觉得 Tooltip 和 Popover 在功能上差不多。但它们在界面交互中 行使的职能 是有区别的。Tooltip 浮层弹框 只在于展示信息,目标组件的依旧可以形式自己的点击事件。比如AndroidStudio 中鼠标悬浮文件名时,展示详细的路径信息,属于 Tooltip 功能:

而 Popover 会可能会消耗目标组件的点击事件,弹出浮层弹框;另外该浮层 可以有消费事件 的需求。这两点是它和 Tooltip 的差异所在。比如 Photoshop 工具悬浮时展示的浮层面板,可以通过 Popover 展示:


四、Popover 的使用

Popover 的使用案例介绍可以网站访问 TolyUI 的 web 版 Flutter 应用。

组件/反馈组件/popover: toly1994.com/ui/#/widget...


1. TolyPopover 的基本使用

TolyPopover 通过 overlay 属性展示浮层面板;builder 方法可以回调控制器,控制器可以主动打开或关闭浮层。如下所示:

左侧案例通过 MouseRegion 监听鼠标进入事件,通过控制器打开浮层:

dart 复制代码
TolyPopover(
  placement: Placement.top,
  maxWidth: 200,
  overlay: const DisplayPanel(),
  builder: (_, ctrl, __) {
    return MouseRegion(
      onEnter: (_)=> ctrl.open(),
      child: const DebugDisplayButton( info: 'Hover Me'),
    );
  },
);

中间的案例通过按钮的点击回调事件 onPressed 方法,通过控制器打开浮层:

dart 复制代码
TolyPopover(
  placement: Placement.top,
  maxWidth: 200,
  overlay: const DisplayPanel(),
  builder: (_, ctrl, __) {
    return DebugDisplayButton( info: 'Click Me', onPressed: ctrl.open);
  },
);

右侧的案例通过 GestureDetector 的长按回调事件 onLongPress 方法,通过控制器打开浮层。除此之外,双击事件,按下事件、抬起事件,甚至是自定义的交互手势,都可以通过控制器来打开或关闭浮层:

dart 复制代码
TolyPopover(
  placement: Placement.top,
  maxWidth: 200,
  overlay: const DisplayPanel(),
  builder: (_, ctrl, __) {
    return GestureDetector(
        onLongPress: ctrl.open, child: const Text('LongPress Me'));
  },
);

2. 浮层弹框中控制关闭

有时需要在浮层中控制浮层自身的关闭,而关闭浮层的关键在于控制器。也就是说,只要让浮层弹框感知到控制器,即可进行操作。此时可以将 overlay 入参升级为 overlayBuilder,来感知控制器:

左侧案例的删除弹框,点击确定或取消后关闭浮层面板。弹框的内容由 DeletePanel 构建,将动画控制器传入其中即可,在点击按键时通过 ctrl 关闭浮层:

dart 复制代码
TolyPopover(
  placement: Placement.top,
  maxWidth: 200,
  overlayBuilder: (_,ctrl) => DeletePanel( ctrl: ctrl),
  builder: (_, ctrl, __) {
    return DebugDisplayButton(
      info: 'Delete',
      onPressed: ctrl.open,
    );
  },
);

右侧案例的添加按钮打开菜单也是类似,通过 DisplayMenu 展示菜单内容,构造时传入控制器。另外,和 TolytTooltip 一样,也可以通过 decorationConfig 来配置气泡框的装饰效果:

dart 复制代码
TolyPopover(
  placement: Placement.bottomEnd,
  maxWidth: 180,
  overlayBuilder: (_, ctrl) => DisplayMenu(ctrl),
  decorationConfig: const DecorationConfig(),
  builder: (_, ctrl, __) {
    return GestureDetector(
      onTap: ctrl.open,
      child: const Padding(
        padding: EdgeInsets.symmetric(horizontal: 4.0),
        child: Icon(Icons.add_circle_outline, color: Color(0xff666666)),
      ),
    );
  },
);

3. 自定义装饰和偏移

如下所示 TolyPopover 可以给使用者足够的发挥空间,来自定义面板内容以及装饰样式。其中通过 overlayDecorationBuilder 函数构造展示,目的是回调 PopoverDecoration 提供一些必要的参数,你可以根据它来更好的自定义装饰。offsetCalculator 也是如此,可以实现如下效果:

左侧案例中,点击头像时展示面板信息。通过 overlayDecorationBuilder 自定义非气泡框的普通装饰;并通过 offsetCalculator 计算偏移量,让弹框左上角和头像的中心对齐:

dart 复制代码
TolyPopover(
  placement: Placement.rightStart,
  maxWidth: 260,
  overlay: const _DisplayPanel(),
  overlayDecorationBuilder: decorationBuilder,
  offsetCalculator: calculatorOffset,
  builder: (_, ctrl, __) {
    return GestureDetector(
      onTap: ctrl.open,
      child: const CircleAvatar(
        backgroundImage: AssetImage('assets/images/icon_head.webp'),
      ),
    );
  },
);

calculatorOffset 负责基于 Calculator 数据计算偏移量。它承载着目标组件尺寸、间隔、对齐方式、浮框尺寸四个数据。这里向下移动目标组件尺寸高度的一半,向左移动间隔加上目标组件尺寸宽度一半,即可让浮层左上角和目标组件中心对齐:

dart 复制代码
//// 计算偏移
Offset calculatorOffset(Calculator calculator){
  double x = calculator.boxSize.width / 2 + calculator.gap;
  double y = calculator.boxSize.height / 2;
  return Offset(-x, y);
}

decorationBuilder 负责自定义装饰,PopoverDecoration 会回调组件尺寸、对齐方式、气泡偏移量三个值。如果你需要自己定义气泡装饰,这些数据将会非常有用。不过这里使用的是普通的 BoxDecoration ,这些数据就没有什么作用了。

dart 复制代码
/// 自定义装饰
Decoration decorationBuilder(PopoverDecoration decoration){
  return BoxDecoration(
    color: Colors.white,
    border: Border.all(color: Colors.black.withOpacity(0.1)),
    boxShadow: [
      BoxShadow(
        color: Colors.black.withOpacity(0.1),
        offset: const Offset(0, 2),
        blurRadius: 6,
        spreadRadius: 0,
      )
    ],
    borderRadius: BorderRadius.circular(4),
  );
}

4. Popover 的 对齐方式

Popover 的 12 种浮窗对齐方式和 TolyTooltip 一样;另外指定的对齐方式在溢出边界后也可以自适应转变:

dart 复制代码
TolyPopover(
  maxWidth: 200,
  placement: Placement.bottom, /// 指定对齐方式
  gap: 12,
  overlay: _DisplayPanel(title: info,),
  builder: (_,ctrl,__)=>
      DebugDisplayButton(info: buttonText ,onPressed: ctrl.open,),
),

尾声

这就是 TolyUI 带来的反馈组件的第一波,也是继响应式布局之后,推出的第二个模块。随着 tolyui 的逐步迭代,越来越多的新功能将会支持。感谢你关注 tolyui 的成长,如果喜欢,也希望你能在 github 中点赞支持~

github 开源地址: github.com/TolyFx/toly...

TolyUI 官方案例演示网站:toly1994.com/ui

TolyUI 的下一步会继续设计打造反馈组件,更多的精彩内容,敬请期待 ~

相关推荐
xiangxiongfly9151 小时前
Android 圆形和圆角矩形总结
android·圆形·圆角·imageview
幻雨様7 小时前
UE5多人MOBA+GAS 45、制作冲刺技能
android·ue5
Jerry说前后端9 小时前
Android 数据可视化开发:从技术选型到性能优化
android·信息可视化·性能优化
Meteors.9 小时前
Android约束布局(ConstraintLayout)常用属性
android
alexhilton10 小时前
玩转Shader之学会如何变形画布
android·kotlin·android jetpack
whysqwhw14 小时前
安卓图片性能优化技巧
android
风往哪边走14 小时前
自定义底部筛选弹框
android
江上清风山间明月14 小时前
Flutter AlwaysScrollableScrollPhysics详解
flutter·滚动·scrollable·scrollphysics
Yyyy48215 小时前
MyCAT基础概念
android
Android轮子哥15 小时前
尝试解决 Android 适配最后一公里
android