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

如何创建带clipPath边框裁剪的Flutter分段选择控件

分段选择控件优化方案

我想要实现如图所示的分段选择控件:
分段选择控件设计图

目前我已经做出了接近的效果,但存在边框间隙和切换时圆角方向异常的问题。以下是我的实现代码:

class SegmentedControl extends Stateful Widget {
  @override
  _SegmentedControlState createState() => _SegmentedControlState();
}

class _SegmentedControlState extends State<SegmentedControl> {
  bool isSpendingSelected = true;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 300,
      height: 50,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(25),
        border: Border.all(
          color: Colors.grey,
        ),
      ),
      child: Stack(
        children: [
          AnimatedPositioned(
            duration: const Duration(milliseconds: 300),
            curve: Curves.easeInOut,
            left: isSpendingSelected ? 0 : 150,
            child: Container(
              width: 150,
              height: 50,
              decoration: BoxDecoration(
                color: const Color(0xFF22303C), // Dark color for selected tab
                borderRadius: BorderRadius.circular(25),
              ),
            ),
          ),
          Row(
            children: [
              Expanded(
                child: GestureDetector(
                  onTap: () {
                    setState(() {
                      isSpendingSelected = true;
                    });
                  },
                  child: Center(
                    child: Text(
                      'Spending',
                      style: TextStyle(
                        color: isSpendingSelected ? Colors.white : Colors.grey,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                ),
              ),
              Expanded(
                child: GestureDetector(
                  onTap: () {
                    setState(() {
                      isSpendingSelected = false;
                    });
                  },
                  child: Center(
                    child: Text(
                      'Saving',
                      style: TextStyle(
                        color: isSpendingSelected ? Colors.grey : Colors.grey,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

问题修复方案

针对上述问题,修改后的代码如下:

class SegmentedControl extends Stateful Widget {
  @override
  _SegmentedControlState createState() => _SegmentedControlState();
}

class _SegmentedControlState extends State<SegmentedControl> {
  bool isSpendingSelected = true;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 300,
      height: 50,
      padding: const EdgeInsets.all(2), // 预留边框空间,解决间隙问题
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(25),
        border: Border.all(color: Colors.grey),
      ),
      child: Stack(
        children: [
          AnimatedPositioned(
            duration: const Duration(milliseconds: 300),
            curve: Curves.easeInOut,
            left: isSpendingSelected ? 0 : 148, // 适配padding后的宽度偏移
            child: Container(
              width: 148, // 300减去左右padding后的均分宽度
              height: 46, // 50减去上下padding后的高度
              decoration: BoxDecoration(
                color: const Color(0xFF22303C),
                // 根据选中状态动态设置圆角,解决方向异常
                borderRadius: isSpendingSelected
                    ? const BorderRadius.only(
                        topLeft: Radius.circular(23),
                        bottomLeft: Radius.circular(23),
                      )
                    : const BorderRadius.only(
                        topRight: Radius.circular(23),
                        bottomRight: Radius.circular(23),
                      ),
              ),
            ),
          ),
          Row(
            children: [
              Expanded(
                child: GestureDetector(
                  onTap: () => setState(() => isSpendingSelected = true),
                  child: Center(
                    child: Text(
                      'Spending',
                      style: TextStyle(
                        color: isSpendingSelected ? Colors.white : Colors.grey,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                ),
              ),
              Expanded(
                child: GestureDetector(
                  onTap: () => setState(() => isSpendingSelected = false),
                  child: Center(
                    child: Text(
                      'Saving',
                      style: TextStyle(
                        // 修正选中时的文本颜色
                        color: isSpendingSelected ? Colors.grey : Colors.white,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

关键修改点说明

  • 边框间隙修复:给外部容器添加2px内边距,让选中容器与外部边框保留间隔,避免覆盖边框导致的视觉缝隙。
  • 圆角方向修复:根据选中状态仅保留对应侧的圆角,切换时不会出现与外部边框冲突的圆角样式。
  • 文本颜色修正:调整"Saving"的文本颜色逻辑,选中时显示白色,与设计图保持一致。

内容的提问来源于stack exchange,提问作者Gbenga B Ayannuga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:08:13