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