【问题标题】:Can I overflow a widget in Container to make it like clipped?我可以溢出 Container 中的小部件以使其像剪辑一样吗?
【发布时间】:2020-08-22 06:46:28
【问题描述】:

我正在按照下面的图片进行操作,但是当我尝试制作那个白色气泡时遇到了一些困难。

我尝试过使用另一篇帖子Flutter mask a circle into a container 中的OverFlowBox 的方法,但我把圆圈卡在Container 的中间,我不知道为什么alignment 不会帮助移动它。这是我尝试过的:

return Container(
  alignment: Alignment.topCenter,
  height: screenHeight/3.5,
  width: screenWidth/3.5,
  decoration: BoxDecoration(
    borderRadius: BorderRadius.only(
      topLeft: Radius.circular(10),
      topRight: Radius.circular(60),
      bottomLeft: Radius.circular(10),
      bottomRight: Radius.circular(10),
    ),
    gradient: LinearGradient(
      begin: FractionalOffset.topLeft,
      end: FractionalOffset.bottomRight,
      colors: [boxColorBegin, boxColorEnd]
    ),
  ),
  child: ClipRect(
    clipBehavior: Clip.hardEdge,
    child: OverflowBox(
      maxHeight: screenHeight/3.5 +20,
      maxWidth: screenWidth/3.5 + 20,
      child:Container(
        decoration: BoxDecoration(
          color: Colors.white,
          shape: BoxShape.circle,
        ),
      )
    ),
  ),
);

结果是

有没有办法让小部件内部的东西溢出,让它看起来像被剪掉了?

提前致谢!

【问题讨论】:

  • 如果你想让某个小部件溢出它的父级,那你为什么要使用剪辑呢?
  • 因为我其实想剪掉溢出的部分
  • 但如果您只想定位您的孩子,您根本不需要OverflowBoxchild: Container( alignment: Alignment.topLeft, clipBehavior: Clip.antiAlias, decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.grey, ), child: FractionalTranslation( translation: Offset(-0.25, -0.5), child: Container( width: 200, height: 200, decoration: BoxDecoration( color: Colors.orange, shape: BoxShape.circle, ), ), ), ),
  • 我看到了,所以您可以使用Container 进行剪辑。我认为您的代码是最简单的代码,没有额外的StackClipRRect 或重复BorderRadius。你想留下答案吗?
  • 当然,欢迎您,顺便说一句,您也可以避免使用FractionalTranslation 而不是Alignment.topLeft 使用Alignment(-1, -2) 或其他东西,但是当使用FractionalTranslation 时,您可以更精确地控制如何定位孩子小部件

标签: flutter


【解决方案1】:

我找到了实现我想要的方法,但仍然对为什么 OverFlowBox 无法对齐感到困惑。我认为这是因为 OverFlowBox 的大小大于其父级,但是当我将其更改为较小的大小时它仍然不起作用。

我使用StackPositioned小部件并将Stack的overflow参数设置为overflow.clip

代码如下:

return Container(
  height: screenHeight/3.5,
  width: screenWidth/3.2,
  decoration: BoxDecoration(
    borderRadius: BorderRadius.only(
      topLeft: Radius.circular(10),
      topRight: Radius.circular(60),
      bottomLeft: Radius.circular(10),
      bottomRight: Radius.circular(10),
    ),
    gradient: LinearGradient(
      begin: FractionalOffset.topLeft,
      end: FractionalOffset.bottomRight,
      colors: [boxColorBegin, boxColorEnd]
    ),
  ),
  child: Stack(
    overflow: Overflow.clip,
    alignment: Alignment.topCenter ,
    children: <Widget>[
      Positioned(
        bottom: screenHeight / 8,
        right: screenWidth / 12,
        child: Container(
          width: screenWidth / 3.5,
          height: screenHeight / 3.5,
          decoration: BoxDecoration(
            color: Colors.white38,
            shape: BoxShape.circle,
          ),
        )
      )
    ],
  )
)

结果是

编辑

事实证明,您可以使用 Container 作为带有 clipBehavior 参数的裁剪器,并使用 FractionalTranslation 小部件作为子小部件来操纵白色圆圈的位置。感谢pskink 的简单回答。

这是新代码

return Container(
  alignment: Alignment.topLeft,
  clipBehavior: Clip.antiAlias,
  height: screenHeight/3.5,
  width: screenWidth/3.2,
  decoration: BoxDecoration(
    borderRadius: BorderRadius.only(
      topLeft: Radius.circular(10),
      topRight: Radius.circular(60),
      bottomLeft: Radius.circular(10),
      bottomRight: Radius.circular(10),
    ),
    gradient: LinearGradient(
      begin: FractionalOffset.topLeft,
      end: FractionalOffset.bottomRight,
      colors: [boxColorBegin, boxColorEnd]
    ),
  ),
  child: FractionalTranslation(
    translation: Offset(-0.25, -0.5),
    child: Container(
      width: screenWidth / 3.5,
      height: screenHeight / 3.5,
      decoration: BoxDecoration(
        color: Colors.white38,
        shape: BoxShape.circle,
      ),
    )
  )
);

【讨论】:

    【解决方案2】:

    您可以使用填充来移动OverflowBox。您还需要使用ClipRRect 剪辑父Container

    这是您的修复方法(经过测试且有效):

    return ClipRRect(
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(10),
                topRight: Radius.circular(60),
                bottomLeft: Radius.circular(10),
                bottomRight: Radius.circular(10),
              ),
              child: Container(
                alignment: Alignment.topCenter,
                height: screenHeight / 3.5,
                width: screenWidth / 3.5,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(10),
                    topRight: Radius.circular(60),
                    bottomLeft: Radius.circular(10),
                    bottomRight: Radius.circular(10),
                  ),
                  gradient: LinearGradient(
                      begin: FractionalOffset.topLeft, end: FractionalOffset.bottomRight, colors: [boxColorBegin, boxColorEnd]),
                ),
                child: ClipRect(
                  clipBehavior: Clip.hardEdge,
                  child: Padding(
                    padding: const EdgeInsets.only(right: 130, bottom: 150),
                    child: OverflowBox(
                        maxHeight: screenHeight / 3.5 + 20,
                        maxWidth: screenWidth / 3.5 + 20,
                        child: Container(
                          decoration: BoxDecoration(
                            color: Colors.white.withAlpha(80),
                            shape: BoxShape.circle,
                          ),
                        )),
                  ),
                ),
              ),
            );
    

    【讨论】:

    • 感谢您的回答,但我可以知道为什么需要使用 ClipRRect 包装容器吗?以及为什么 OverFlowBox 不能对齐?
    • 这样白色圆圈就不会画在框外。只需删除 ClipRRect 并查看
    【解决方案3】:

    您可以使用 ClipRRect 作为此小部件的根容器轻松完成此操作。为它提供一个边界半径,它将剪裁所有孩子并防止他们在边界之外绘画。然后,您可以使用 Transform.translate 渲染一个圆圈并将其偏移到其父级之外。

    I created a sample pen for you to try

    return ClipRRect(
      borderRadius: BorderRadius.only(
        topLeft: Radius.circular(8),
        bottomLeft: Radius.circular(8),
        bottomRight: Radius.circular(8),
        topRight: Radius.circular(125),
      ),
      child: Container(
        height: 400,
        width: 250,
        decoration: BoxDecoration(
          color: Colors.red,
        ),
        child: Stack(
          children: [
            Align(
              alignment: Alignment.topLeft,
              child: Transform.translate(
                offset: Offset(-40, -100),
                child: Container(
                  height: 220,
                  width: 220,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.all(Radius.circular(110)),
                    color: Colors.white.withOpacity(0.4),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
    

    有关 ClipRRectTransform.translate 的更多信息,请访问 API 文档。

    【讨论】:

      猜你喜欢
      • 2016-09-13
      • 1970-01-01
      • 2013-05-07
      • 1970-01-01
      • 2020-10-29
      • 2019-05-14
      • 2011-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多