flutter RenderFlex溢出错误只出现在小部件测试中,如果我运行应用程序,一切正常

n3schb8v  于 2023-11-21  发布在  Flutter
关注(0)|答案(1)|浏览(226)

一个最小的可重复的例子可以在这里找到:https://github.com/HerrNiklasRaab/repro-widget-test-overflow
我现在的app看起来是这样的:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
      home: Scaffold(
    body: DashboardNewsItem(),
  )));
}

class DashboardNewsItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      width: 165,
      height: 100,
      child: Row(
        children: <Widget>[
          Text(
            "Zu Instagram",
          ),
          Icon(Icons.arrow_forward)
        ],
      ),
    );
  }
}

字符串
如果我在设备上运行这个,它看起来像下面这样:

一旦我用下面的小部件测试运行这个:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:test_ble/main.dart';

void main() {
  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
        home: Scaffold(
      body: DashboardNewsItem(),
    )));
  });
}


我得到这个例外:

Counter increments smoke test:

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following assertion was thrown during layout:
A RenderFlex overflowed by 27 pixels on the right.

The relevant error-causing widget was:
  Row file:///Users/niklasraab/GitHub/test_ble/lib/main.dart:19:14

The overflowing RenderFlex has an orientation of Axis.horizontal.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be
seen. If the content is legitimately bigger than the available space, consider clipping it with a
ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
like a ListView.
The specific RenderFlex in question is: RenderFlex#abc37 OVERFLOWING:
  creator: Row ← ColoredBox ← ConstrainedBox ← Container ← DashboardNewsItem ← _BodyBuilder ←
    MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ← AnimatedBuilder ←
    DefaultTextStyle ← AnimatedDefaultTextStyle ← ⋯
  parentData: <none> (can use size)
  constraints: BoxConstraints(w=165.0, h=100.0)
  size: Size(165.0, 100.0)
  direction: horizontal
  mainAxisAlignment: start
  mainAxisSize: max
  crossAxisAlignment: center
  textDirection: ltr
  verticalDirection: down
◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
════════════════════════════════════════════════════════════════════════════════════════════════════
ERROR: Test failed. See exception logs above.
The test description was: Counter increments smoke test


当然,我可以像这样将文本 Package 在Flexible中:

class DashboardNewsItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      width: 165,
      height: 100,
      child: Row(
        children: <Widget>[
          Flexible(
            child: Text(
              "Zu Instagram",
            ),
          ),
          Icon(Icons.arrow_forward)
        ],
      ),
    );
  }
}


但是我不需要这样做,因为文本在水平轴上有足够的空间,所以有人能给我解释一下这种有线行为吗?

sqyvllje

sqyvllje1#

如果你直接在模拟器上运行测试,它会通过。

flutter run -d emulator test\widget_test.dart

字符串
我个人直接在我的设备上运行它,测试通过了。
问题是它不会在所有设备上通过。在某些设备上,165个逻辑像素的宽度可能不足以包含TextIcon。对于Flutter提供的默认测试环境来说,这可能是真的。通常,让你的小部件尽可能响应是个好主意。因此,一个更好的实现是删除widthheight约束,改为约束Row的大小,并使用padding

class DashboardNewsItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      padding: const EdgeInsets.symmetric(
          horizontal: 24.0, vertical: 16.0), // or any other value
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(
            "Zu Instagram",
          ),
          Icon(Icons.arrow_forward)
        ],
      ),
    );
  }
}

相关问题