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

如何在Flutter中实现如图所示的自定义Tab组件?

Flutter 实现自定义Tab样式

根据你提供的样式需求,这里给出一种直接的实现方案,通过自定义Tab组件结合状态控制来还原效果:

核心实现思路

  • 自定义Tab子组件,根据选中状态切换背景、文字样式及装饰
  • 借助DefaultTabController管理选中索引,同步所有Tab的状态
  • 隐藏系统默认的Tab指示器,完全用自定义样式替代

完整代码示例

import 'package:flutter/material.dart';

void main() => runApp(const CustomTabDemo());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('自定义Tab示例')),
        body: const DefaultTabController(
          length: 3,
          child: Column(
            children: [
              CustomTabBar(),
              Expanded(child: TabBarView(
                children: [
                  Center(child: Text('首页内容')),
                  Center(child: Text('分类内容')),
                  Center(child: Text('我的内容')),
                ],
              )),
            ],
          ),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final tabController = DefaultTabController.of(context)!;
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      decoration: const BoxDecoration(
        color: Color(0xFFF5F5F5),
        borderRadius: BorderRadius.vertical(bottom: Radius.circular(16)),
      ),
      child: TabBar(
        controller: tabController,
        indicator: const BoxDecoration(), // 隐藏默认指示器
        labelPadding: const EdgeInsets.symmetric(horizontal: 8),
        tabs: [
          _CustomTabItem(title: '首页', isSelected: tabController.index == 0),
          _CustomTabItem(title: '分类', isSelected: tabController.index == 1),
          _CustomTabItem(title: '我的', isSelected: tabController.index == 2),
        ],
        onTap: (index) => tabController.animateTo(index),
      ),
    );
  }
}

class _CustomTabItem extends StatelessWidget {
  final String title;
  final bool isSelected;

  const _CustomTabItem({required this.title, required this.isSelected});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
      decoration: BoxDecoration(
        color: isSelected ? Colors.white : Colors.transparent,
        borderRadius: const BorderRadius.all(Radius.circular(20)),
        boxShadow: isSelected
            ? [
                BoxShadow(
                  color: Colors.grey.withOpacity(0.2),
                  blurRadius: 4,
                  offset: const Offset(0, 2),
                )
              ]
            : null,
      ),
      child: Text(
        title,
        style: TextStyle(
          color: isSelected ? Colors.blue : Colors.grey,
          fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
        ),
      ),
    );
  }
}

样式调整说明

如果需要匹配图中更细节的样式(比如底部弧形选中条),可以修改_CustomTabItem为以下实现:

class _CustomTabItem extends StatelessWidget {
  final String title;
  final bool isSelected;

  const _CustomTabItem({required this.title, required this.isSelected});

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.bottomCenter,
      children: [
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
          child: Text(
            title,
            style: TextStyle(
              color: isSelected ? Colors.blue : Colors.grey,
              fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
            ),
          ),
        ),
        // 底部弧形选中标识
        if (isSelected)
          Container(
            margin: const EdgeInsets.only(bottom: -8),
            width: 24,
            height: 12,
            decoration: const BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
            ),
          ),
      ],
    );
  }
}

你可以根据实际需求调整颜色、圆角大小、阴影参数等,完全自定义出和图中一致的样式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 04:22:45