开始的时候好好的
突然就奔放起来了
没想到,没想到啊
一、现象
界面突然风格变了。
字体变大了,而且没有指定颜色的,用了大红色。 Text都有黄色的双下划线。
这个代码没有改动的。正常情况应该是:
这是想要的效果。
二、结论
flutter_easyloading: ^4.0.2
升级后导致问题。上一个版本3.0.5是2022.05.23 发布的,终于发布4.X版本,更新日志没有说会影响到啥。没想到对于showCupertinoModalPopup()竟然会有样式的影响。
解决方法
在EasyLoading初始化的时候,修改为:
builder: EasyLoading.init(
builder: (context, child) {
return DefaultTextStyle(style: Theme.of(context).textTheme.bodyMedium!, child: child!);
},
)
找了很久没有找到原因,还是AI帮我找到的。以后我应该是测试人员,而不是开发人员了。
三、原因
对EasyLoading的初始化是一样的。
MaterialApp(
initialRoute: "/",
builder: EasyLoading.init(),
)
1. 旧版本
EasyLoading在3.0.5版本中:
@override
Widget build(BuildContext context) {
return Material(
child: Overlay(
initialEntries: [
EasyLoadingOverlayEntry(
builder: (BuildContext context) {
if (widget.child != null) {
return widget.child!;
} else {
return Container();
}
},
),
_overlayEntry,
],
),
);
}
这个 Material 会给下面的根 Navigator/Overlay 提供正常的 Material 默认文字样式。
所以在使用 showCupertinoModalPopup的时候用到了EasyLoading设置的Material。
2. 新版本
EasyLoading在4.X版本中:
@override
Widget build(BuildContext context) {
_syncOverlay();
final session = easyLoadingRuntime.session;
return Stack(
fit: StackFit.passthrough,
clipBehavior: Clip.none,
children: <Widget>[
Material(
type: MaterialType.transparency,
textStyle: DefaultTextStyle.of(context).style,
child: widget.child ?? const SizedBox.shrink(),
),
if (session != null)
Positioned.fill(
child: _EasyLoadingOverlay(
key: _overlayKey,
session: session,
onPresented: () => easyLoadingRuntime.didPresent(session.id),
onDismiss: () {
unawaited(
easyLoadingRuntime.dismiss(
reason: EasyLoadingDismissReason.tap,
),
);
},
),
),
],
);
}
}
设置的textStyle为 DefaultTextStyle.of(context).style, 也就是MaterialApp中的样式。
SO showCupertinoModalPopup使用到了EasyLoading设置的Material。
3. 原因
执行了showCupertinoModalPopup后的图层结构为:
MaterialApp
└─ EasyLoading 包装层
└─ 根 Navigator
└─ Overlay
├─ 原页面 Route
│ └─ Scaffold
│ └─ 正常 Material 文字环境
│
└─ CupertinoModalPopupRoute
└─ CouponPackageDetail
CouponPackageDetail 为弹窗中的视图,它没有设置Material。SO 继承了根Navigator上面的EasyLoading包装层的Material。
旧版本
没有指定textStyle,所以使用了默认的Theme.of(context).textTheme.bodyMedium.
新版本
指定textStyle为DefaultTextStyle.of(context).style,此DefaultTextStyle获取到的是MaterialApp中的textStyle:
Widget _buildWidgetApp(BuildContext context) {
final Color materialColor = widget.color ?? widget.theme?.primaryColor ?? Colors.blue;
if (_usesRouter) {
return WidgetsApp.router(
key: GlobalObjectKey(this),
routeInformationProvider: widget.routeInformationProvider,
routeInformationParser: widget.routeInformationParser,
routerDelegate: widget.routerDelegate,
routerConfig: widget.routerConfig,
backButtonDispatcher: widget.backButtonDispatcher,
onNavigationNotification: widget.onNavigationNotification,
builder: _materialBuilder,
title: widget.title,
onGenerateTitle: widget.onGenerateTitle,
textStyle: _errorTextStyle,
color: materialColor,
locale: widget.locale,
localizationsDelegates: _localizationsDelegates,
localeResolutionCallback: widget.localeResolutionCallback,
localeListResolutionCallback: widget.localeListResolutionCallback,
supportedLocales: widget.supportedLocales,
showPerformanceOverlay: widget.showPerformanceOverlay,
showSemanticsDebugger: widget.showSemanticsDebugger,
debugShowCheckedModeBanner: widget.debugShowCheckedModeBanner,
exitWidgetSelectionButtonBuilder: _exitWidgetSelectionButtonBuilder,
moveExitWidgetSelectionButtonBuilder: _moveExitWidgetSelectionButtonBuilder,
tapBehaviorButtonBuilder: _tapBehaviorButtonBuilder,
shortcuts: widget.shortcuts,
actions: widget.actions,
restorationScopeId: widget.restorationScopeId,
);
}
在_MaterialAppState中build设置为_errorTextStyle:
const TextStyle _errorTextStyle = TextStyle(
color: Color(0xD0FF0000),
fontFamily: 'monospace',
fontSize: 48.0,
fontWeight: FontWeight.w900,
decoration: TextDecoration.underline,
decorationColor: Color(0xFFFFFF00),
decorationStyle: TextDecorationStyle.double,
debugLabel: 'fallback style; consider putting your text in a Material',
);
对,就是它,看到的就是它。
如果弹窗等``
四、 Overlay
Overlay 是 Flutter 中专门用来“叠加显示 UI”的一个容器。它允许新的 Widget 覆盖在当前页面上面,而不需要替换当前页面。
Navigator中的Overlay有很多Route:
Navigator
└─ Overlay
├─ Route A
├─ Route B
├─ Dialog Route
├─ Popup Route
└─ 其他浮层
在执行showCupertinoModalPopup的时候:
MaterialApp
│
└─ EasyLoading
│
└─ Navigator
│
└─ Overlay
│
├─ 原页面 Route
│ └─ Scaffold
│ └─ 页面内容
│
├─ ModalBarrier
│ └─ 半透明遮罩
│
└─ CupertinoModalPopupRoute
└─ CouponPackageDetail
CouponPackageDetail不是弹窗所在的页面的child,而是创建了一个route: CupertinoModalPopupRoute, 所以不会继承原页面的Material。
完结
AI时代,没有AI解决不了的问题。如果不能,请升级套餐。 _