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

Flutter中如何正确水平定位组件以避免横向溢出?

问题说明

我实现了一个自定义Tab Bar组件,现在的问题是Tab项会横向溢出需要滚动才能查看全部,我希望所有Tab能同时显示在一行里,不会出现横向溢出的情况。

当前效果:Tab项横向排列超出屏幕范围,需要滑动才能查看所有选项
期望效果:所有Tab项均匀分配宽度,完整显示在一行内

以下是我的代码片段:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';

class JobsHeaderWidget extends StatefulWidget {
  const JobsHeaderWidget({
    Key key,
  }) : super(key: key);

  @override
  State<JobsHeaderWidget> createState() => _JobsHeaderWidgetState();
}

class _JobsHeaderWidgetState extends State<JobsHeaderWidget> {
  List<String> items = [
    "All",
    "Critical",
    "Open",
    "Closed",
    "Overdue",
  ];

  int current = 0;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(left: 10.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            'Jobs',
            style: GoogleFonts.poppins(
                color: Colors.black, fontSize: 18, fontWeight: FontWeight.w600),
          ),
          Row(
            children: [
              Text(
                'View Insights  ',
                style: GoogleFonts.poppins(
                    color: Color(0xff3498DB),
                    fontSize: 12,
                    fontWeight: FontWeight.w500),
              ),
              Icon(
                Icons.arrow_forward_ios,
                color: Color(0xff3498DB),
                size: 12,
              ),
            ],
          ),
          filterJobs()
        ],
      ),
    );
  }

  Widget filterJobs() {
    return Container(
      width: double.infinity,
      child: Column(
        children: [
          /// CUSTOM TABBAR
          SizedBox(
            width: double.infinity,
            height: 60,
            child: ListView.builder(
                physics: const BouncingScrollPhysics(),
                itemCount: items.length,
                scrollDirection: Axis.horizontal,
                itemBuilder: (ctx, index) {
                  return Column(
                    children: [
                      GestureDetector(
                        onTap: () {
                          setState(() {
                            current = index;
                          });
                        },
                        child: AnimatedContainer(
                          duration: const Duration(milliseconds: 300),
                          margin: const EdgeInsets.all(5),
                          decoration: BoxDecoration(
                            color: current == index
                                ? Color(0xff34495E)
                                : Color(0xffF5F5F5),
                            borderRadius: BorderRadius.circular(11),
                          ),
                          child: Center(
                            child: Padding(
                              padding: const EdgeInsets.only(
                                  left: 10.0, right: 10.0, top: 5, bottom: 5),
                              child: Text(
                                items[index],
                                style: GoogleFonts.poppins(
                                    fontSize: 10,
                                    fontWeight: FontWeight.w500,
                                    color: current == index
                                        ? Colors.white
                                        : Colors.grey),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  );
                }),
          ),

          // Builder(
          //   builder: (context) {
          //     switch (current) {
          //       case 0:
          //         return AllNotificationItemsView();
          //       case 1:
          //         return JobsNotificationItemsView();
          //       case 2:
          //         return MessagesNotificationItemsView();
          //       case 3:
          //         return CustomersNotificationItemsView();
          //       default:
          //         return SizedBox.shrink();
          //     }
          //   },
          // )
        ],
      ),
    );
  }
}
解决方案

要实现所有Tab同时显示且不溢出,只需要把原来的ListView.builder替换成Row,并给每个Tab项外层包裹Expanded,让所有Tab平分可用宽度:

修改步骤:

  1. 将SizedBox内的ListView.builder替换为Row
  2. 给每个Tab项(Column外层)添加Expanded,确保每个Tab占据相等宽度
  3. 移除原来ListView的滚动相关属性(physics、scrollDirection)

修改后的完整代码:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';

class JobsHeaderWidget extends StatefulWidget {
  const JobsHeaderWidget({
    Key key,
  }) : super(key: key);

  @override
  State<JobsHeaderWidget> createState() => _JobsHeaderWidgetState();
}

class _JobsHeaderWidgetState extends State<JobsHeaderWidget> {
  List<String> items = [
    "All",
    "Critical",
    "Open",
    "Closed",
    "Overdue",
  ];

  int current = 0;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(left: 10.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            'Jobs',
            style: GoogleFonts.poppins(
                color: Colors.black, fontSize: 18, fontWeight: FontWeight.w600),
          ),
          Row(
            children: [
              Text(
                'View Insights  ',
                style: GoogleFonts.poppins(
                    color: Color(0xff3498DB),
                    fontSize: 12,
                    fontWeight: FontWeight.w500),
              ),
              Icon(
                Icons.arrow_forward_ios,
                color: Color(0xff3498DB),
                size: 12,
              ),
            ],
          ),
          filterJobs()
        ],
      ),
    );
  }

  Widget filterJobs() {
    return Container(
      width: double.infinity,
      child: Column(
        children: [
          /// CUSTOM TABBAR
          SizedBox(
            width: double.infinity,
            height: 60,
            child: Row( // 替换为Row
              children: List.generate(items.length, (index) {
                return Expanded( // 添加Expanded
                  child: Column(
                    children: [
                      GestureDetector(
                        onTap: () {
                          setState(() {
                            current = index;
                          });
                        },
                        child: AnimatedContainer(
                          duration: const Duration(milliseconds: 300),
                          margin: const EdgeInsets.all(5),
                          decoration: BoxDecoration(
                            color: current == index
                                ? Color(0xff34495E)
                                : Color(0xffF5F5F5),
                            borderRadius: BorderRadius.circular(11),
                          ),
                          child: Center(
                            child: Padding(
                              padding: const EdgeInsets.symmetric(
                                  horizontal: 8, vertical: 5), // 适配宽度调整padding
                              child: Text(
                                items[index],
                                textAlign: TextAlign.center, // 确保文字居中
                                style: GoogleFonts.poppins(
                                    fontSize: 10,
                                    fontWeight: FontWeight.w500,
                                    color: current == index
                                        ? Colors.white
                                        : Colors.grey),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                );
              }),
            ),
          ),

          // Builder(
          //   builder: (context) {
          //     switch (current) {
          //       case 0:
          //         return AllNotificationItemsView();
          //       case 1:
          //         return JobsNotificationItemsView();
          //       case 2:
          //         return MessagesNotificationItemsView();
          //       case 3:
          //         return CustomersNotificationItemsView();
          //       default:
          //         return SizedBox.shrink();
          //     }
          //   },
          // )
        ],
      ),
    );
  }
}

说明:

  • 使用Row配合Expanded让每个Tab自动平分父容器的宽度,确保所有Tab在一行显示且不溢出
  • 给Text添加textAlign: TextAlign.center避免文字过长时显示不全
  • 调整了padding为symmetric,让左右内边距更适配平分后的宽度

内容的提问来源于stack exchange,提问作者tesseract

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:40:52