theme: cyanosis
本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!
《Flutter TolyUI 框架》系列前言:
TolyUI 是 张风捷特烈 打造的 Fluter 全平台应用开发 UI 框架。具备 全平台、组件化、源码开放、响应式 四大特点。可以帮助开发者迅速构建具有响应式全平台应用软件:
该系列将详细介绍 TolyUI 框架使用方式、框架开发过程中的技术知识、设计理念、难题解决等。
一、全局消息通知设计
全局消息通知是 UI 框架中非常重要且基本的功能,Flutter 本身并没有完善的全局信息通知功能。只有 Scaffold 组件可以弹出 SnackBar ,但这对全平台应用,特别是桌面端应用来说是不够用的。为此 TolyUI 中提供了 Message(消息) 和 Notification(通知) 两个功能,让用户可以非常方便地实现全局的信息提示、
1.全局消息设计动机
虽然 pub 上有一些 Toast 库,但功能比较单一。特别是在连续多次弹出消息时,消息会重复展示在同一位置。这在界面语义上来说是非常糟糕的。所以 TolyUI 希望提供一个:
可高度定制、具有偏移动画的,全局消息通知模块。
下面是 TolyUI 中实现的效果,消息可以由上放或下方弹出。弹出时消息组件有 透明度
和 偏移
两个动画效果,另外上方的消息移除时,下方的消息会有向上平移的动画。下方消息同理。
TolyUI 中将这种全局展示操作反馈信息称之为 Message,它的职能在于:
- 展示成功、警告和错误等反馈信息,并在指定时间后可自动消失。
- 消息不会打断用户交互,是一种轻量级的交互反馈。
2.全局通知设计动机
有时应用会产出一些通知,这些通知往往具有更复杂的信息,而且有时不希望被自动关闭。所以推出 Notification(通知) 概念,它和消息类似的,但职能要更丰富一些。如下所示:
- 通知可以展示定位在在全局的四个角落;
- 通知一般具有更复杂的展示内容;
- 通知在语义上,是系统级通知的被动提醒;
- 通知可被主动关闭,也可以设置不被自动关闭。
3. tolyui_message 模块
为了让 TolyUI 的功能模块可以细粒度地服务于开发者,采取模块化的分包模式。之前我们已经将反馈模块分为了 tolyuifeedback,但考虑到全局消息提示是一个独立的功能,在 tolyuifeedback 之下又提供了一个 tolyui_message 的独立模块。
这样 tolyui 的模块化将呈现一个树形结构,父节点的模块可以享用子模块的所有功能。同时子模块又可以单独存在,服务于开发者。比如开发者可能只想用消息通知的包,可以直接用 tolyui_message,它可以不知道 TolyUI 的存在,而使用 TolyUI 的模块功能。
TolyUI 已经寻找到了一种基于单体功能模块,组织复杂框架的手段。我所描绘的是一张 Flutter 全平台 UI 框架的蓝图,它为 Flutter 全平台开发指明方向。虽然目前只有我一人推进,但后期如果有更多开发者加入到 TolyUI 的建设中,合理的模块划分也可以更好地让更多人参与合作。
二、全局消息提示的使用
下面来正式介绍一下代码中的具体使用方式。全局消息和通知,本质上是基于全局浮层实现的,首先你需要在应用的顶层设置嵌套 TolyMessage 组件:
dart void main() { runApp(TolyMessage(child: MyApp())); }
1. 全局消息定位与富文本
如下所示,全局消息提示有上下两种定位方式,多次触发时会进行动画偏移展示。这也是 TolyUI 消息提示最重要的亮点,也是我花费很大心力才最终实现的:
对于开发者来说,你可以非常精简使用这项功能。如下所示,在任何事件中,触发 $message.info
传入文章信息即可展示 info 样式的消息框:
dart $message.info(message: 'This is a common message.');
想要从底部展示消息,可以设置 position
参数,指定为 MessagePosition.bottom
:
dart $message.info( message: 'This is a common message.', position: MessagePosition.bottom, );
如果想要展示富文本,可以通过 richMessage
参数进行设置,提供 InlineSpan :
```dart InlineSpan span = const TextSpan(children: [ TextSpan(text: '请通过此邮箱联系我 '), TextSpan(style: TextStyle(color: Colors.blue), text: '1981462002@qq.com ') ]);
$message.info(richMessage: span); ```
2. 四种消息类型
为了便于开发者使用, $message
对象提供了四个方法,分别返回成功(success)
、警告(warning)
、信息(info)
、错误(error)
四种类型的消息;另外设置 plain:true
可以让消息样式变为白色背景、阴影边框。
dart // 成功 $message.success(message: 'Congrats, this is a success message.'); // 警告 $message.warning(message: 'Warning, this is a warning message.'); // 信息 $message.info(message: 'This is a common message.'); // 错误 $message.error(message: 'Oops, this is a error message.');
3.自定义消息内容组件
使用者可以通过 $message.emit
方法,展示自定义的组件内容。 animaDuration 控制动画时长;duration 控制展示时长;offset 控制消息的偏移。
比如这里展示信息的面板是 DebugDisplayPanel
组件,可以将它作为 child
参数:
dart $message.emit(child: const DebugDisplayPanel( image: 'assets/images/icon_head.webp', title: '张风捷特烈', info1: '微信号: zdl1994328', info2: '地区: 安徽·合肥', ));
默认提示信息展示 3 秒,动画时长为 250 ms, 可以通过 duration 和 animaDuration 来自定义这两个时长。另外默认在竖直方向上偏移 16 逻辑像素,可以通过 offset 参数设置偏移量:
dart $message.emit( position: MessagePosition.bottom, offset: const Offset(0, 10), duration: const Duration(seconds: 2), animaDuration: const Duration(milliseconds: 500), child: const DebugDisplayPanel( image: 'assets/images/icon_head.webp', title: '张风捷特烈', info1: '微信号: zdl1994328', info2: '地区: 安徽·合肥', ), );
4.可关闭的消息
TolyUI 的 message 支持主动关闭,关闭之后,下方的消息会自动动画上移,补齐空位。自定义的消息,可以通过 builder 回调访问关闭函数。
普通的消息,通过 closeable:true
即可让其可关闭:
dart $message.success( closeable: true, duration: const Duration(seconds: 5), message: 'Congrats, this is a success message.', );
关闭自定义的组件是个稍微复杂点的问题,因为关闭函数是封装在类库之内的。外界需要访问关闭函数,也就是说需要一种方式将内部的东西暴露出来。没错,这就是 回调函数。通过 builder 参数可以回调 close 方法,将其作为关闭事件的处理内容即可:
dart $message.emit( duration: const Duration(seconds: 5), builder: (_, close) => DebugDisplayPanel( image: 'assets/images/icon_head.webp', title: '张风捷特烈', info1: '微信号: zdl1994328', info2: '地区: 安徽·合肥', onClose: close, ), );
三、全局通知的使用
全局通知是一个可以定位在四角的消息面板,同样也具有 自动消失、动画偏移、动画进入 的展示效果。它也是基于 $message
对象触发相关的方法来打开的。
1. 是否自动关闭
Notification 默认从右上角自右向左动画展出,在 3 秒后自动移除。也提供了不自动关闭的设置方式:
通过 $message.XXXNotice
就可以展开对应样式的通知,其中 XXX 和上面的消息提示一致。比如 info 级别的通知使用 $message.infoNotice,其中可以设置 title
和 subtitle
两个组件内容:
```dart String title = 'Notification Title'; String subtitle = 'I will be close automatically'*3; TextStyle titleStyle = const TextStyle(fontSize: 16, fontWeight: FontWeight.bold);
$message.infoNotice( title: Text(title, style: titleStyle), subtitle: Text(subtitle), ); ```
如果不想通知栏自动关闭,可以将 duration 时长设为 0,由用户主动关闭:
dart $message.infoNotice( duration: Duration.zero, /// 不自动关闭 title: Text(title, style: titleStyle), subtitle: Text(subtitle), );
2. 通知的四角定位
通知可以通过 NoticePosition
枚举设置在四角的位置,分别是左上、左下、右上、右下。另外,也有 成功(success)
、警告(warning)
、信息(info)
、错误(error)
,如下图所示:
dart enum NoticePosition { topLeft, topRight, bottomLeft, bottomRight; }
比如在左下角展示成功的通知,通过 successNotice
方法,将 position
设置为 NoticePosition.bottomLeft
:
dart $message.successNotice( position: NoticePosition.bottomLeft, title: Text( 'Success Notification', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), subtitle: Text('This is a Notification from bottomLeft.'*3)); },
3. 自定义通知内容与偏移
通过 $message.emitNotice 方法可以自定义通知内容组件,其中回调的 close 函数用于关闭通知。offset 属性可以设置提示面板偏移量。
同样,在 build 回调函数中可以访问关闭函数,代码如下所示:
dart $message.emitNotice( builder: (_, close) => DebugDisplayPanel( image: 'assets/images/icon_head.webp', title: '张风捷特烈', info1: '微信号: zdl1994328', info2: '地区: 安徽·合肥', onClose: close, ), );
三、消息通知的主题设置与暗亮模式
建议在一个 App 中消息和通知可以统一风格,为此 TolyUI 提供消息通知的主题配置,便于开发者统一配置默认样式。毕竟不是所有的应用都想使用 TolyUI 的默认风格,提供给使用者足够的灵活性,也是 TolyUI 的设计原则之一。
1. 可配置的主题数据
TolyUI 中将消息和提示的行为和视图表现分为两个主题。其中时长、位置、偏移等弹出时的配置数据,通过TolyMessageShowTheme 提供默认主题:
dart final Duration? duration; final Duration? animaDuration; final MessagePosition? messagePosition; final NoticePosition? noticePosition; final Offset? noticeOffset; final Offset? offset; final double? gap;
视图表现相关的主题,比如四种样式的颜色、背景色、图标,边框圆角、是否可关闭等。通过TolyMessageStyleTheme 提供默认主题:
```dart final MessageStyle successStyle; final MessageStyle infoStyle; final MessageStyle errorStyle; final MessageStyle warningStyle; final BorderRadius? borderRadius; final BorderRadius? noticeBorderRadius; final bool? plain; final bool? closeable;
class MessageStyle { final IconData icon; final Color backgroundColor; final Color foregroundColor; final Color borderColor;
```
2. TolyUI 主题的使用
拓展主题的使用在 《响应式布局#使用篇》 中介绍过基于主题自定义响应式尺阶的解析逻辑。这里也是一样,在 ThemeData 的 extensions
参数中提供相关主题数据。TolyUI 中提供了默认的主题数据,你也可以自己构建 TolyMessageShowTheme
和 TolyMessageStyleTheme
对象:
暗色主题的消息配色提供了 TolyMessageStyleTheme.tolyuiDark()
,这里通过两处的配置,可以让展示的时长默认为 5 秒。
最后,由于全局的消息提示是在 MaterialApp
之上的。如果在其下,弹出的消息将会在对话框下方,效果不佳。但应用的主题数据一般设置在 MaterialApp 之下,这就会导致全局浮层的上下文无法响应暗亮主题变化。为此需要为 TolyMessage
提供和 MaterialApp 一致的主题数据与主题模式。代码如下:
dart @override Widget build(BuildContext context) { AppState state = context.watch<AppLogic>().state; ThemeData light = lightTheme; ThemeData dark = darkTheme; ThemeMode mode = state.themeMode; return TolyMessage( theme: light, darkTheme: dark, themeMode: mode, child: MaterialApp.router( routerConfig: _router, debugShowCheckedModeBanner: false, theme: light, darkTheme: dark, themeMode: mode, title: 'TolyUI', ), ); }
这样配置之后,消息提示与通知面板就可以支持暗色模式。简体的配色方案,你也可以通过主题进行自定义。
目前为止,TolyUI 以及完成了响应式布局和反馈模块的核心功能。消息通知模块的完成,大大增加了 TolyUI 的可用性。随着 tolyui 的逐步迭代,越来越多的新功能将会支持。
感谢你关注 tolyui 的成长,如果喜欢,也希望你能在 github 中点赞支持\~
github 开源地址: https://github.com/TolyFx/toly_ui\ TolyUI 官方案例演示网站:http://toly1994.com/ui