在Flutter中,Tabbar会将一些选项卡的内容拉伸到超出屏幕宽度的范围。

4
在以下代码中,你会看到我在选项卡栏中有三个选项卡。分别是Analytics(分析)、Quality Control(质量控制)和Inventory(库存)。
当你不访问第三个选项卡时,前两个选项卡都能正常工作。但是当你转到第三个选项卡时,你会发现选项卡的内容会以奇怪的方式扩展宽度,并且内容也会超出屏幕限制。这并不会在调试控制台中引发任何错误。
另外,如果你转到另一个页面然后再返回第三个页面,这个问题就会解决,内容大小也会恢复正常。以下是它的样子: 这是内容被拉伸的屏幕样式 这是屏幕应该呈现的样子 以下是Dashboard的代码:
class DashboardScreen extends StatelessWidget {
  static const String routeName = '/dashboard';

  const DashboardScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3, 
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Dashboard'),
          centerTitle: true,
          bottom: const TabBar(
            tabs: [
              Tab(
                text: 'Overview',
                icon: Icon(Icons.analytics),
              ),
              Tab(
                text: 'QC History',
                icon: Icon(Icons.verified_user),
              ),
              Tab(
                text: 'Inventory Stock',
                icon: Icon(Icons.inventory),
              ),
            ],
          ),
        ),
        body: TabBarView(
          children: [
            const AnalyticsScreen(),
            const QualityControlScreen(),
            InventoryScreen(),
          ],
        ),
      ),
    );
  }
}

这是库存屏幕的代码(我说的第三个选项卡):
class InventoryScreen extends StatelessWidget {
  static const String routeName = '/inventory';

  InventoryScreen({Key? key}) : super(key: key);

  // Dummy data representing items in the factory's inventory
  final List<InventoryItem> inventoryItems = [
    InventoryItem(
      name: 'Item A',
      quantity: 10,
      description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
    ),
    InventoryItem(
      name: 'Item B',
      quantity: 5,
      description:
          'Ut enim ad minim veniam, quis nostrud exercitation ullamco.',
    ),
    InventoryItem(
      name: 'Item C',
      quantity: 15,
      description: 'Duis aute irure dolor in reprehenderit in voluptate velit.',
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: inventoryItems.length,
      itemBuilder: (context, index) {
        final item = inventoryItems[index];

        return CustomCardWidget(
          child: Column(
            children: [
              ListTile(
                title: Text(item.name),
                subtitle: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text('Quantity: ${item.quantity}'),
                    const SizedBox(height: 4),
                    Text(item.description),
                  ],
                ),
                onTap: () {
                  // TODO: Handle tapping on an inventory item
                },
              ),
              const SizedBox(height: 8),
              LinearProgressIndicator(
                value: item.quantity / 100,
              ),
              const SizedBox(height: 8),
              SizedBox(
                height: 200,
                child: SfCartesianChart(
                  primaryXAxis: CategoryAxis(),
                  series: <ChartSeries>[
                    ColumnSeries<InventoryItem, String>(
                      dataSource: [item],
                      xValueMapper: (InventoryItem item, _) => item.name,
                      yValueMapper: (InventoryItem item, _) => item.quantity,
                      color: Colors.blue,
                    ),
                  ],
                ),
              ),
            ],
          ),
        );
      },
    );
  }
}

此外,这里还有其他屏幕的代码,供参考比较:
class QualityControlScreen extends StatelessWidget {
  static const String routeName = '/quality-control';

  const QualityControlScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const SingleChildScrollView(
      child: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          children: [
            QualityControlItem(
              testId: 'QC001',
              testName: 'Test A',
              status: QualityControlStatus.passed,
            ),
            QualityControlItem(
              testId: 'QC002',
              testName: 'Test B',
              status: QualityControlStatus.failed,
            ),
            QualityControlItem(
              testId: 'QC003',
              testName: 'Test C',
              status: QualityControlStatus.pending,
            ),
          ],
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return const SingleChildScrollView(
      child: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            ProductionProgress(),
            Attendance(),
            InventoryStock(),
            QualityControlHistory(),
          ],
        ),
      ),
    );
  }
}

我尝试将第三个选项卡的ListView.builder更改为SingleChildScrollView,但没有任何变化。
编辑:我将第三个选项卡的内容替换为一个文本小部件,问题仍然存在。我不认为这与页面的内容有关。
另外,只有在有3个选项卡的情况下才会出现这个问题。我尝试了2、4、5个选项卡,没有问题。

你的SfCartesianChart位于一个带有高度参数但没有宽度的SizedBox小部件中。你可以尝试添加一个固定的宽度吗?例如:width: MediaQuery.of(context).size.width - 5 - Texv
你的SfCartesianChart位于一个带有高度参数但没有宽度的SizedBox小部件中。你可以尝试添加一个固定的宽度吗?例如:width: MediaQuery.of(context).size.width - 5 - undefined
正如我在问题的结尾提到的,页面的内容并不重要。我已经尝试用文本小部件替换内容,但结果并没有改变。当控制器中有4个选项卡时,同样的小部件可以正常工作。 - OZTech Lab
我能理解。这可能是在渲染过程中的一个问题。指定宽度会强制进行内容内的渲染。另外,你有试过在实体设备上测试吗? - Texv
2个回答

2
我面临着一个非常相似的问题,也是有3个选项卡,它总是导航到最后一个选项卡,从而造成了扭曲。更改内容没有任何效果。
然而,这个问题只在Android模拟器上出现。我无法在实际的移动设备上复现此错误,也无法在Linux桌面应用程序上渲染。因此,我怀疑这是一个模拟器的错误。

0
只有在Android模拟器上出现。 并且在将Flutter从3.10升级到3.13后问题得到解决。
flutter upgrade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接