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

Flutter中如何去除按钮下半部分内边距并实现指定按钮样式?

Flutter按钮自定义形状与左侧模糊效果实现

问题解决代码

Widget _buildDepositButton(CodDepositionProvider provider, BuildContext context) {
  final buttonWidth = 151.0;
  final extendWidth = 4.0; // 上半部分额外扩展宽度
  final buttonHeight = 48.0; // 按钮总高度,可根据内容调整

  return Positioned(
    left: 0,
    right: 0,
    top: 237 - 30,
    child: Center(
      child: GestureDetector(
        onTap: () {},
        child: Stack(
          alignment: Alignment.center,
          children: [
            // 上半部分扩展的白色背景
            ClipPath(
              clipper: _ButtonTopExtendClipper(extendWidth: extendWidth, radius: 30),
              child: Container(
                width: buttonWidth + 2 * extendWidth,
                height: buttonHeight,
                color: Colors.white,
              ),
            ),
            // 蓝色主体按钮
            Container(
              width: buttonWidth,
              height: buttonHeight,
              decoration: BoxDecoration(
                color: const Color(0xFF0066FF),
                borderRadius: BorderRadius.circular(30),
              ),
              child: Stack(
                children: [
                  // 左侧模糊效果层
                  Positioned(
                    left: 0,
                    top: 0,
                    bottom: 0,
                    width: buttonWidth / 3, // 模糊区域宽度,可自定义
                    child: BackdropFilter(
                      filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
                      child: Container(
                        color: Colors.white.withOpacity(0.2), // 模糊层底色透明度
                        decoration: const BoxDecoration(
                          borderRadius: BorderRadius.only(
                            topLeft: Radius.circular(30),
                            bottomLeft: Radius.circular(30),
                          ),
                        ),
                      ),
                    ),
                  ),
                  // 按钮核心内容
                  const Padding(
                    padding: EdgeInsets.symmetric(horizontal: 16, vertical: 13),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        CustomImageView(
                          imagePath: "assets/images/diagonal_arrow.svg",
                        ),
                        SizedBox(width: 6),
                        Text(
                          'Deposit Now',
                          textAlign: TextAlign.right,
                          style: TextStyle(
                            color: Color(0xFFEDF2F4),
                            fontSize: 14,
                            fontFamily: 'Poppins',
                            fontWeight: FontWeight.w500,
                            letterSpacing: -0.28,
                          ),
                        )
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    ),
  );
}

// 自定义裁剪器:实现上半部分扩展、下半部分与主体对齐的形状
class _ButtonTopExtendClipper extends CustomClipper<Path> {
  final double extendWidth;
  final double radius;

  _ButtonTopExtendClipper({required this.extendWidth, required this.radius});

  @override
  Path getClip(Size size) {
    final path = Path();
    final centerX = size.width / 2;
    final buttonHalfWidth = (size.width - 2 * extendWidth) / 2;

    // 左上角圆角路径
    path.moveTo(extendWidth, radius);
    path.arcToPoint(
      Offset(extendWidth + radius, 0),
      radius: Radius.circular(radius),
      clockwise: false,
    );
    // 顶部右侧直线
    path.lineTo(size.width - extendWidth - radius, 0);
    // 右上角圆角路径
    path.arcToPoint(
      Offset(size.width - extendWidth, radius),
      radius: Radius.circular(radius),
      clockwise: false,
    );
    // 右侧向下到主体按钮右边缘
    path.lineTo(centerX + buttonHalfWidth, size.height);
    // 右下角圆角(与主体按钮匹配)
    path.arcToPoint(
      Offset(centerX + buttonHalfWidth - radius, size.height - radius),
      radius: Radius.circular(radius),
      clockwise: true,
    );
    // 底部左侧直线
    path.lineTo(centerX - buttonHalfWidth + radius, size.height - radius);
    // 左下角圆角(与主体按钮匹配)
    path.arcToPoint(
      Offset(centerX - buttonHalfWidth, size.height),
      radius: Radius.circular(radius),
      clockwise: true,
    );
    // 左侧向上回到起点
    path.lineTo(extendWidth, radius);

    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

关键实现说明

1. 上半部分扩展形状解决

  • 放弃嵌套Container+padding的方案,改用ClipPath配合自定义裁剪器_ButtonTopExtendClipper,精确绘制白色背景的形状:
    • 顶部左右向外扩展指定宽度,保留圆角
    • 下半部分严格与蓝色主体按钮对齐,圆角弧度和主体保持一致
    • 彻底消除底部左右的多余白色区域,完全符合需求

2. 左侧模糊效果实现

  • 在蓝色主体按钮内部嵌套Stack,添加BackdropFilter组件:
    • 通过ImageFilter.blur调整模糊强度(sigmaX/sigmaY值越大越模糊)
    • 模糊层使用半透明白色底色,既保留按钮原有色调,又增强模糊视觉效果
    • 限制模糊层宽度为按钮的1/3(可根据设计需求调整),并设置左侧圆角与按钮匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 16:26:00