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

如何在Flutter中复刻Tinder式兴趣选择组件?

组件名称

这个组件是多选兴趣标签选择器,和Tinder的兴趣选择组件功能一致,核心是提供可点击切换选中状态的标签集合,并支持最低选择数量限制(你需求中的至少3个)。

Flutter实现方案

1. 核心状态管理

使用StatefulWidget维护选中标签集合与选择数量校验状态:

class InterestTagSelector extends StatefulWidget {
  final List<String> tags;
  final int minSelection;

  const InterestTagSelector({
    super.key,
    required this.tags,
    this.minSelection = 3,
  });

  @override
  State<InterestTagSelector> createState() => _InterestTagSelectorState();
}

class _InterestTagSelectorState extends State<InterestTagSelector> {
  final Set<String> _selectedTags = {};
  bool _hasEnoughSelection = false;

  @override
  void initState() {
    super.initState();
    _checkSelectionCount();
  }

  void _toggleTag(String tag) {
    setState(() {
      _selectedTags.contains(tag) ? _selectedTags.remove(tag) : _selectedTags.add(tag);
      _checkSelectionCount();
    });
  }

  void _checkSelectionCount() {
    setState(() => _hasEnoughSelection = _selectedTags.length >= widget.minSelection);
  }

2. 标签UI与交互实现

用Wrap实现流式布局,根据选中状态切换标签样式,同时添加数量校验提示:

@override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Wrap(
          spacing: 8.0,
          runSpacing: 8.0,
          children: widget.tags.map((tag) {
            final isSelected = _selectedTags.contains(tag);
            return GestureDetector(
              onTap: () => _toggleTag(tag),
              child: Container(
                padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                decoration: BoxDecoration(
                  color: isSelected ? Colors.pinkAccent : Colors.grey[200],
                  borderRadius: BorderRadius.circular(20),
                ),
                child: Text(
                  tag,
                  style: TextStyle(
                    color: isSelected ? Colors.white : Colors.black87,
                    fontSize: 14,
                  ),
                ),
              ),
            );
          }).toList(),
        ),
        // 未达标提示
        if (!_hasEnoughSelection)
          Padding(
            padding: const EdgeInsets.only(top: 12),
            child: Text(
              '请至少选择${widget.minSelection}个兴趣标签',
              style: TextStyle(color: Colors.red[400], fontSize: 12),
            ),
          ),
        // 确认按钮(按需添加)
        if (_hasEnoughSelection)
          Padding(
            padding: const EdgeInsets.only(top: 20),
            child: ElevatedButton(
              onPressed: () => print('选中标签:$_selectedTags'),
              style: ElevatedButton.styleFrom(
                backgroundColor: Colors.pinkAccent,
                fixedSize: const Size(double.infinity, 48),
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
              ),
              child: const Text('确认', style: TextStyle(color: Colors.white)),
            ),
          ),
      ],
    );
  }
}

3. 组件调用示例

在页面中直接传入标签列表即可使用:

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

  final List<String> _tags = const [
    '音乐', '电影', '运动', '美食', '旅行', '读书',
    '摄影', '游戏', '健身', '绘画', '宠物', '科技'
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('选择兴趣')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: InterestTagSelector(tags: _tags),
      ),
    );
  }
}

可选扩展功能

  • 添加标签搜索过滤:结合TextField实时筛选标签列表
  • 自定义样式:支持传入自定义颜色、圆角、字体大小参数
  • 选中动画:添加AnimatedContainer实现选中时的过渡动画

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:05:21