【问题标题】:Flutter Button Stack - Icon needs to overlap parentFlutter Button Stack - 图标需要与父级重叠
【发布时间】:2021-10-04 17:35:04
【问题描述】:

我有一个按钮,需要将图标放置在矩形之外。

我可以用 Stack 很好地做到这一点,但是按钮边框与图标重叠,如您在此处看到的:

它应该看起来像这样:

这是我的代码:

OutlinedButton(
                style: scansButtonStyle,
                onPressed: () {}, // TODO: add later
                child: Stack(clipBehavior: Clip.none, children: [
                  Padding(
                    padding: const EdgeInsets.only(left: 50.0),
                    child: Text('CONNECT'),
                  ),
                  Positioned(
                    bottom: 0,
                    left: -20,
                    child: CircleAvatar(
                      radius: 30,
                      backgroundColor: Colors.black,
                      child: CircleAvatar(
                        radius: 27,
                        backgroundColor: Colors.white,
                        child: Icon(
                          Icons.bluetooth_connected,
                          color: Colors.black,
                          size: 48,
                        ),
                      ),
                    ),
                  ),
                ]),
              ),

和样式:

final ButtonStyle scansButtonStyle = OutlinedButton.styleFrom(
    alignment: Alignment.centerLeft,
    primary: Colors.black,
    backgroundColor: Color(0xfffcd722),
    minimumSize: Size(242, 48),
    padding: EdgeInsets.fromLTRB(20, 3, 20, 3),
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.only(
          topLeft: Radius.circular(16),
          topRight: Radius.zero,
          bottomRight: Radius.circular(16),
          bottomLeft: Radius.zero),
    ),
    textStyle: const TextStyle(
      color: Colors.black,
      fontWeight: FontWeight.w600,
      fontSize: 34,
      fontFamily: 'HP',
    ),
    side: BorderSide(
      color: Colors.black,
      width: 3.0,
      style: BorderStyle.solid,
    ));

【问题讨论】:

  • 可以分享你期待的图片吗?
  • 我对其进行了编辑以包含预期的图像

标签: flutter button stack overlap


【解决方案1】:

我已经稍微更正了代码。
主要变化是:

  1. 将大纲按钮放入堆栈中
  2. 将 CircleAvatar 更改为带有装饰的简单 Container(您真的需要 CircleAvatar 吗?您会以任何方式为图标设置动画吗?如果没有,那么简单的 Container 可能会更好)
  3. 将 IgnorePointer 添加到图标,以便它忽略点击事件并将其传递给按钮本身(即使在图标上按下时也会产生波纹效果)
  4. 用 FittedBox 小部件包裹图标并向外部容器添加填充。这将允许我们的图标根据外圆的大小动态更改其大小。
  5. 为文本小部件添加了一些参数,以便在文本长于宽度时不会破坏设计。您可以使用 Text('CONNECT' * 10) 进行检查
Stack(
                  clipBehavior: Clip.none,
                  children: [
                    OutlinedButton(
                      onPressed: () {},
                      style: scansButtonStyle,
                      child: Padding(
                        padding: const EdgeInsets.only(left: 50.0),
                        child: Text(
                          'CONNECT',
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                          textScaleFactor: 1.0, // We do not want OS preferences (text scale option) to break our button's design
                        ),
                      ),
                    ),
                    Positioned(
                      bottom: 0,
                      child: IgnorePointer(
                        //ignore touch events, so that the Outlined button triggers touch animation when pressed on the icon
                        child: SizedBox(
                          width: 60.0,
                          child: AspectRatio(
                            aspectRatio: 1.0,
                            child: Container(
                              padding: EdgeInsets.all(6.0),
                              decoration: BoxDecoration(
                                color: Colors.white,
                                border: Border.all(
                                  color: Colors.black,
                                  width: 3.0,
                                ),
                                shape: BoxShape.circle,
                              ),
                              child: FittedBox(
                                child: Icon(
                                  Icons.bluetooth_connected,
                                  color: Colors.black,
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                )

代码可能需要进一步调整,但你会明白的。

还请注意,图标的顶部不占用任何空间(因为 Clip.none 和它在堆栈中的位置)。您可以通过将按钮包装在彩色容器中来测试它。

如果您不喜欢 SizedBox 中的 AspectRatio 的想法 - 将其改回 Container 中的宽度/高度。

【讨论】:

  • 太棒了 - 只需对图标位置进行微小的调整,它看起来并完全符合我的要求 - 无论我点击图标还是按钮(至少是重叠部分),我都可以触发按钮是我所需要的。谢谢!
【解决方案2】:

通过将按钮和图标放入堆栈(而不是按钮内的堆栈),我已经实现了所需的视觉效果。

这里的缺点是,如果我现在点击图标,它不再触发按钮。

所以这个答案不太正确......

Stack(
   clipBehavior: Clip.none,
                children: [
                  OutlinedButton(
                  style: scansButtonStyle,
                  onPressed: () {}, // TODO: add later
                  child: Padding(
                    padding: const EdgeInsets.only(left: 50.0),
                    child: Text('CONNECT'),
                  ),
                    ),
                  Positioned(
                    bottom: 6,
                    left: 0,
                    child: CircleAvatar(
                      radius: 30,
                      backgroundColor: Colors.black,
                      child: CircleAvatar(
                        radius: 27,
                        backgroundColor: Colors.white,
                        child: Icon(
                          Icons.bluetooth_connected,
                          color: Colors.black,
                          size: 48,
                        ),
                      ),
                    ),
                  ),
              ]),

【讨论】:

  • 我想一种解决方法是让图标也成为链接到相同功能的按钮 - 不确定这是否是最优雅的解决方案?老实说,问题中的图标仅由与按钮重叠的部分触发-但它足够接近以至于不足以引起问题-而此解决方案在按钮上创建了一个无法触发的孔:(
猜你喜欢
  • 2016-07-09
  • 2020-03-02
  • 2022-01-25
  • 2016-06-14
  • 1970-01-01
  • 2014-09-13
  • 2013-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多