You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 17:25:30