Flutter使用MediaQuery动态设字体大小遇No MediaQuery祖先错误
解决方案:No MediaQuery widget ancestor found 错误
错误原因
你在MyApp的build方法中使用的context属于MyApp组件本身,而MediaQuery是由MaterialApp插入到widget树中的。此时MaterialApp是MyApp的子组件,所以当前context无法找到MediaQuery祖先节点。
解决方法
方法一:通过MaterialApp的builder属性获取正确的Context
利用builder属性可以拿到MaterialApp内部的context(已包含MediaQuery),再基于此修改主题:
import 'package:flutter/material.dart'; void main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Navigation Basics', builder: (innerContext, child) { // innerContext 是 MaterialApp 内部的上下文,可访问 MediaQuery final customTextTheme = Theme.of(innerContext).textTheme.copyWith( bodyText1: TextStyle( fontSize: getFontSize(innerContext), ), ); return Theme( data: ThemeData( primarySwatch: Colors.deepPurple, textTheme: customTextTheme, ), child: child!, ); }, home: const Homepage(), ); } } double getFontSize(BuildContext context) { var screenWidth = MediaQuery.of(context).size.width; return screenWidth <= 992 ? 40 : 32; } class Homepage extends StatelessWidget { const Homepage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center(child: Text('测试文本', style: Theme.of(context).textTheme.bodyText1)), ); } }
方法二:在子组件中计算字体大小
将字体大小的计算逻辑移到MaterialApp的子组件(比如Homepage)中,子组件的context可以正常访问MediaQuery:
import 'package:flutter/material.dart'; void main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Navigation Basics', theme: ThemeData( primarySwatch: Colors.deepPurple, ), home: const Homepage(), ); } } double getFontSize(BuildContext context) { var screenWidth = MediaQuery.of(context).size.width; return screenWidth <= 992 ? 40 : 32; } class Homepage extends StatelessWidget { const Homepage({super.key}); @override Widget build(BuildContext context) { final fontSize = getFontSize(context); return Scaffold( body: Center( child: Text('测试文本', style: TextStyle(fontSize: fontSize)), ), ); } }
方法三:直接获取窗口尺寸(不推荐)
如果不需要依赖widget树的MediaQuery,可以直接通过窗口信息获取屏幕宽度,但这种方式在多窗口、分屏等场景下可能不准确:
double getFontSize() { var screenWidth = MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.width; return screenWidth <= 992 ? 40 : 32; }
然后在主题中直接调用getFontSize()即可,无需传入context。
内容的提问来源于stack exchange,提问作者Aseem
相关产品推荐
相关产品推荐

