如何通过MediaQuery结合if语句在ThemeData中动态设置字体大小?
问题解答
可行性说明
完全可以通过屏幕尺寸动态设置ThemeData中的字体大小,只是需要注意获取屏幕尺寸的时机,避免上下文报错问题。
报错原因
你在MyApp的build方法中调用MediaQuery.of(context)时,当前context属于MyApp组件,而MyApp的父级并没有提供MediaQuery(MediaQuery是由MaterialApp内部注入的上下文数据),因此无法通过这个context获取到屏幕尺寸信息,导致报错。
实现方案
方案一:无需上下文,直接通过系统窗口获取屏幕尺寸
适合仅在初始化时设置字体大小,不需要响应屏幕旋转等动态变化的场景。
修改后的代码:
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { // 获取屏幕逻辑尺寸(去除设备像素比影响) final window = WidgetsBinding.instance.window; final screenSize = window.physicalSize / window.devicePixelRatio; final screenWidth = screenSize.width; // 自定义字体大小规则:屏幕宽度小于360时用14,否则用16 final bodyTextFontSize = screenWidth < 360 ? 14.0 : 16.0; return MaterialApp( theme: ThemeData.dark().copyWith( scaffoldBackgroundColor: Colors.black, textTheme: TextTheme( bodyText1: TextStyle( fontWeight: FontWeight.bold, fontFamily: 'SourceSansPro', fontSize: bodyTextFontSize, ), ), ), debugShowCheckedModeBanner: false, initialRoute: '/second', routes: { '/': (context) => pageone(), '/first': (context) => pagetwo(), '/second': (context) => pagethree(), }, ); } }
方案二:通过Builder获取有效上下文,响应屏幕动态变化
适合需要在屏幕尺寸改变(比如旋转)时自动更新字体大小的场景。
修改后的代码:
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return Builder( builder: (context) { // 此时的context已包含MaterialApp提供的MediaQuery数据 final screenSize = MediaQuery.of(context).size; final bodyTextFontSize = screenSize.width < 360 ? 14.0 : 16.0; return MaterialApp( theme: ThemeData.dark().copyWith( scaffoldBackgroundColor: Colors.black, textTheme: TextTheme( bodyText1: TextStyle( fontWeight: FontWeight.bold, fontFamily: 'SourceSansPro', fontSize: bodyTextFontSize, ), ), ), debugShowCheckedModeBanner: false, initialRoute: '/second', routes: { '/': (context) => pageone(), '/first': (context) => pagetwo(), '/second': (context) => pagethree(), }, ); }, ); } }
补充说明
- 方案一的优势是初始化性能更高,但不会自动响应屏幕尺寸的动态变化;
- 方案二会在屏幕尺寸改变时自动重建
MaterialApp,从而更新字体大小,适配更灵活; - 如果需要全局所有文本样式都适配屏幕尺寸,只需在
TextTheme的其他样式(如bodyText2、headline6等)中复用相同的字体大小判断逻辑即可。
内容的提问来源于stack exchange,提问作者Nomad09
相关产品推荐
相关产品推荐

