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

Flutter中如何创建如图所示的特殊组合自定义按钮?

Flutter实现右端包裹圆形按钮的自定义按钮

直接上可运行的代码实现,你可以复制到项目里调试:

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: CustomWrapButton(
            onRectTap: () => print('矩形区域被点击'),
            onCircleTap: () => print('圆形按钮被点击'),
            rectText: '执行操作',
            circleIcon: Icons.add,
          ),
        ),
      ),
    );
  }
}

class CustomWrapButton extends StatelessWidget {
  final VoidCallback onRectTap;
  final VoidCallback onCircleTap;
  final String rectText;
  final IconData circleIcon;

  const CustomWrapButton({
    super.key,
    required this.onRectTap,
    required this.onCircleTap,
    required this.rectText,
    required this.circleIcon,
  });

  @override
  Widget build(BuildContext context) {
    const circleSize = 56.0;
    const rectPadding = EdgeInsets.symmetric(horizontal: 24, vertical: 16);
    const rectBorderRadius = BorderRadius.only(
      topLeft: Radius.circular(8),
      bottomLeft: Radius.circular(8),
      topRight: Radius.circular(circleSize / 2),
      bottomRight: Radius.circular(circleSize / 2),
    );

    return Stack(
      alignment: Alignment.centerRight,
      children: [
        // 底层矩形按钮区域
        GestureDetector(
          onTap: onRectTap,
          child: Container(
            // 右侧留一半圆形宽度的内边距,避免文字被遮挡
            padding: rectPadding.add(const EdgeInsets.only(right: circleSize / 2)),
            decoration: BoxDecoration(
              color: Colors.blue.shade50,
              borderRadius: rectBorderRadius,
              border: Border.all(color: Colors.blue.shade300),
            ),
            child: Text(
              rectText,
              style: TextStyle(
                fontSize: 16,
                color: Colors.blue.shade700,
                fontWeight: FontWeight.w500,
              ),
            ),
          ),
        ),
        // 上层圆形按钮
        ElevatedButton(
          onPressed: onCircleTap,
          style: ElevatedButton.styleFrom(
            fixedSize: const Size(circleSize, circleSize),
            shape: const CircleBorder(),
            backgroundColor: Colors.blue,
            elevation: 2,
          ),
          child: Icon(circleIcon, color: Colors.white),
        ),
      ],
    );
  }
}

关键实现细节:

  • 用Stack做层叠布局,让圆形按钮刚好卡在矩形右端,形成视觉上的“包裹”效果。
  • 矩形右上角和右下角的圆角半径设为圆形按钮直径的一半,保证边缘和圆形完美贴合。
  • 给矩形右侧加了一半圆形宽度的内边距,防止文字被圆形按钮遮挡。
  • 两个区域分别绑定独立点击事件,互不干扰。

扩展调整建议:

  • 如果想要整个组合按钮有统一的水波纹反馈,可以把Stack套在InkWell里,注意圆形按钮的点击优先级更高。
  • 可以把颜色、尺寸、圆角这些值抽成组件参数,方便复用不同样式的按钮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 02:27:33