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

Flutter中TextField不显示,出现RenderBox无尺寸点击测试错误

问题

开发一款沉浸式闹钟Flutter应用,用户需完成答题任务才能关闭闹钟。使用TextField实现答题输入时,触发Cannot hit test a render box with no size错误,且TextField无法正常显示。

错误信息:

throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Cannot hit test a render box with no size.'),
          describeForError('The hitTest() method was called on this RenderBox'),
          ErrorDescription(
            'Although this node is not marked as needing layout, '
            'its size is not set.',
          ),
          ErrorHint(
            'A RenderBox object must have an '
            'explicit size before it can be hit-tested. Make sure '
            'that the RenderBox in question sets its size during layout.',
          ),
        ]);
      }

完整代码:

import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
//import 'package:audioplayers/audio_cache.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Time Attack',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          backgroundColor: Colors.red,
          title: const Text('Time Attack'),
          centerTitle: true,
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () async {
            // ignore: avoid_print
            print("alarm is playing");
            final player = AudioCache();
            //bool isPLaying = false;
            await player.load('musicForapp.mp3');
            AudioPlayer p = AudioPlayer();
            p.audioCache = player;
            await p.play(AssetSource('musicForapp.mp3'));
          },
          backgroundColor: Colors.red,
          child: const Icon(Icons.punch_clock),
        ),
        body: Padding(
          padding: const EdgeInsets.all(170),
          child: Column(
            children: [
              const Text(
                "Click the Icon in the bottem right to simulate alarm",
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 30.0,
                ),
              ),
              ElevatedButton(
                style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (_) => const TasksPage(),
                    ),
                  );
                }, //on pressed
                child: const Text(
                  "Tasks page",
                  style: TextStyle(color: Colors.white),
                ),
              )
            ],
          ),
        ),
      ),
    );
  } //widget build
}

class TasksPage extends StatefulWidget {
  const TasksPage({super.key});

  @override
  State<TasksPage> createState() => _TasksPageState();
}

class _TasksPageState extends State<TasksPage> {
  final _textcontroller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          backgroundColor: Colors.red,
          title: const Text('Tasks'),
          centerTitle: true,
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => const SecondTask(),
              ),
            );
          },
          backgroundColor: Colors.red,
          child: const Text("Next"),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                const Text(
                  "How many states are there in the United States of America?",
                  style: TextStyle(
                    backgroundColor: Colors.white,
                    color: Colors.black,
                    fontSize: 30.0,
                  ),
                ),
                Expanded(
                  child: TextField(
                    controller: _textcontroller,
                    decoration: InputDecoration(
                      hintText: "Type your answer here!",
                      border: const OutlineInputBorder(),
                      suffixIcon: IconButton(
                        onPressed: () {
                          _textcontroller.clear();
                        },
                        icon: const Icon(Icons.clear),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  } //widget build
}

class SecondTask extends StatefulWidget {
  const SecondTask({super.key});

  @override
  State<SecondTask> createState() => _SecondTask();
}

class _SecondTask extends State<SecondTask> {
  final _textcontroller2 = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          backgroundColor: Colors.red,
          title: const Text('Tasks'),
          centerTitle: true,
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => const Thirdtask(),
              ),
            );
          },
          backgroundColor: Colors.red,
          child: const Text("Next"),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                const Text(
                  "how many oceans are there?",
                  style: TextStyle(
                    backgroundColor: Colors.white,
                    color: Colors.black,
                    fontSize: 30.0,
                  ),
                ),
                Expanded(
                  child: TextField(
                    controller: _textcontroller2,
                    decoration: InputDecoration(
                      hintText: "Type your answer here!",
                      border: const OutlineInputBorder(),
                      suffixIcon: IconButton(
                        onPressed: () {
                          _textcontroller2.clear();
                        },
                        icon: const Icon(Icons.clear),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  } //widget build
}

class Thirdtask extends StatefulWidget {
  const Thirdtask({super.key});

  @override
  State<Thirdtask> createState() => _Thirdtask();
}

class _Thirdtask extends State<Thirdtask> {
  final _textcontroller3 = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          backgroundColor: Colors.red,
          title: const Text('Tasks'),
          centerTitle: true,
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => const Finaltask(),
              ),
            );
          },
          backgroundColor: Colors.red,
          child: const Text("Next"),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                const Text(
                  "What is 8 x 7?",
                  style: TextStyle(
                    backgroundColor: Colors.white,
                    color: Colors.black,
                    fontSize: 30.0,
                  ),
                ),
                Expanded(
                  child: TextField(
                    controller: _textcontroller3,
                    decoration: InputDecoration(
                      hintText: "Type your answer here!",
                      border: const OutlineInputBorder(),
                      suffixIcon: IconButton(
                        onPressed: () {
                          _textcontroller3.clear();
                        },
                        icon: const Icon(Icons.clear),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  } //widget build
}

class Finaltask extends StatefulWidget {
  const Finaltask({super.key});

  @override
  State<Finaltask> createState() => _Finaltask();
}

class _Finaltask extends State<Finaltask> {
  final _textcontroller4 = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          backgroundColor: Colors.red,
          title: const Text('Tasks'),
          centerTitle: true,
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => const Congrats(),
              ),
            );
          },
          backgroundColor: Colors.red,
          child: const Text("Submit"),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                const Text(
                  "Riddle: What goes up but never comes back down?",
                  style: TextStyle(
                    backgroundColor: Colors.white,
                    color: Colors.black,
                    fontSize: 30.0,
                  ),
                ),
                Expanded(
                  child: TextField(
                    controller: _textcontroller4,
                    decoration: InputDecoration(
                      hintText: "Type your answer here!",
                      border: const OutlineInputBorder(),
                      suffixIcon: IconButton(
                        onPressed: () {
                          _textcontroller4.clear();
                        },
                        icon: const Icon(Icons.clear),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  } //widget build
}

class Congrats extends StatefulWidget {
  const Congrats({super.key});

  @override
  State<Congrats> createState() => _Congrats();
}

class _Congrats extends State<Congrats> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          backgroundColor: Colors.red,
          title: const Text('Good Job!'),
          centerTitle: true,
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => const MyHomePage(),
              ),
            );
            //player.clear('explosion.mp3');  (to stop alarm)
            // ignore: avoid_print
            print("Alarm has stoped");
          },
          backgroundColor: Colors.red,
          child: const Text("Home"),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: const [
                Expanded(
                  child: Text(
                    "Congratulations you completed your tasks, Click the home button to return home and stop the timer!",
                    style: TextStyle(
                      backgroundColor: Colors.white,
                      color: Colors.black,
                      fontSize: 30.0,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  } //widget build
}
解决方案

问题根源

  • 重复嵌套MaterialApp:每个页面都重新创建MaterialApp,导致上下文混乱,布局计算异常。Flutter应用仅需一个根MaterialApp。
  • Row布局约束冲突:长文本未开启自动换行,且Row中TextField的空间分配不合理,导致RenderBox无法计算有效尺寸。
  • 音频API弃用:使用了已弃用的AudioCache,存在潜在资源加载问题。

修复步骤

  1. 移除页面中的MaterialApp:仅保留根MyApp中的MaterialApp,其他页面直接返回Scaffold。
  2. 优化文本与TextField布局:
    • 给文本添加Flexible并开启softWrap: true,实现自动换行避免溢出。
    • 将Row布局改为Column,让文本和TextField垂直排列,适配小屏幕。
    • 给TextField设置固定宽度(基于屏幕宽度比例),确保尺寸明确。
  3. 替换音频API:使用AudioPlayer直接加载资源,同时添加资源释放逻辑避免内存泄漏。

修改后完整代码

import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Time Attack',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  AudioPlayer? _audioPlayer;

  @override
  void dispose() {
    _audioPlayer?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        backgroundColor: Colors.red,
        title: const Text('Time Attack'),
        centerTitle: true,
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          print("alarm is playing");
          _audioPlayer = AudioPlayer();
          await _audioPlayer?.play(AssetSource('musicForapp.mp3'));
        },
        backgroundColor: Colors.red,
        child: const Icon(Icons.punch_clock),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              "Click the Icon in the bottom right to simulate alarm",
              style: TextStyle(
                color: Colors.white,
                fontSize: 20.0,
              ),
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 30),
            ElevatedButton(
              style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (_) => const TasksPage(),
                  ),
                );
              },
              child: const Text(
                "Tasks page",
                style: TextStyle(color: Colors.white),
              ),
            )
          ],
        ),
      ),
    );
  }
}

class TasksPage extends StatefulWidget {
  const TasksPage({super.key});

  @override
  State<TasksPage> createState() => _TasksPageState();
}

class _TasksPageState extends State<TasksPage> {
  final _textcontroller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        backgroundColor: Colors.red,
        title: const Text('Tasks'),
        centerTitle: true,
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (_) => const SecondTask(),
            ),
          );
        },
        backgroundColor: Colors.red,
        child: const Text("Next"),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Flexible(
                child: Text(
                  "How many states are there in the United States of America?",
                  style: TextStyle(
                    backgroundColor: Colors.white,
                    color: Colors.black,
                    fontSize: 24.0,
                  ),
                  textAlign: TextAlign.center,
                  softWrap: true,
                ),
              ),
              const SizedBox(height: 20),
              SizedBox(
                width: MediaQuery.of(context).size.width * 0.8,
                child: TextField(
                  controller: _textcontroller,
                  decoration: InputDecoration(
                    hintText: "Type your answer here!",
                    border: const OutlineInputBorder(),
                    suffixIcon: IconButton(
                      onPressed: () {
                        _textcontroller.clear();
                      },
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 23:35:20