删除 UIButton 层上的 CAShapeLayer 遮罩,以便取消遮罩动画 UIButton 大小更改

发布于 2024-12-07 20:48:29 字数 2662 浏览 0 评论 0原文

我有一个自定义按钮类型的 UIButton,我只是在按钮的底层 CALayer 上设置背景和边框颜色。然后,我将遮罩应用到由 CAShapeLayer 组成的底层(以获得两个圆角),如 这篇文章

到目前为止,一切都很好。我对 UIButton 进行动画处理以使其尺寸变大。到目前为止,一切都很好。参见下文(图像中的所有内容都是 _fusedBar,保存您在其下方看到的 x 轴线片段和美元金额文本)。

完全成长的 UIButton 在代码中称为 _fusedBar

当我使用相同的动画例程但不同的参数对 UIButton 进行动画缩小时值(仿射平移与同时帧高度变化),当收缩发生时,没有任何 UIButton(除了一个条子)是可见的。

我尝试让 CAShapeLayer(即蒙版)将其自身从其超级层中删除,我尝试将 UIButton 层上的蒙版属性设置为 nil 等,但这些都没有删除蒙版,以便我可以看到UIButton 动画(随着仿射平移和框架高度变化而缩小)。

这是相关的动画代码:

// Stackoverflow readers: Assume 'duration', 'scaledHeight' and 'delay' 
// already defined.

void (^fusedBarChange)(void) = ^{    
    _fusedBar.transform = CGAffineTransformMakeTranslation(0, -scaledHeight);
    [_fusedBar nd_setNewSizeHeight:scaledHeight];
};

[UIView animateWithDuration:duration
                      delay:delay
                    options:UIViewAnimationCurveEaseOut 
                 animations:^(void) {
                     fusedBarChange();
                 }
                 completion:^(BOOL finished) {
                     // Other stuff not relevant to _fusedBar animation
                 }];

在调用该动画之前,我根据上面引用的帖子进行了蒙版设置。该代码如下。请注意,“_fusedBar”是本次讨论的核心 UIButton。

- (void)configureRoundedTop {
    // YES: Start by creating the path (with only the top-left corner rounded)
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:_fusedBar.bounds 
                                                   byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight
                                                         cornerRadii:CGSizeMake(4.0, 4.0)];

    // Create the shape layer and set its path
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = _fusedBar.bounds;
    maskLayer.path = maskPath.CGPath;

    // Set the newly created shape layer as the mask for the image view's layer
    _fusedBar.layer.mask = maskLayer;
}

当 _fusedBar 从一条条增长到几百点时,增长是动画的,您可以看到它。

在使用这个 CAShapeLayer 蒙版之前,当将 _fusedBar 缩小回一条条时,我可以看到动画(上面的代码相同,只是“scaledHeight”的值不同)。现在,我看不到缩小的动画。

所以,我知道我需要在动画收缩操作之前以某种方式摆脱遮罩层的影响,但明显的事情(对我来说)并没有起作用。下面是我尝试过的各种事情的示例:

// None of these do the trick. I call them just before 
// the shrinking animation is invoked:
[_fusedBar setNeedsLayout];
[_fusedBar setNeedsDisplay];
[_fusedBar.layer.mask removeFromSuperlayer];
_fusedBar.layer.mask = nil;

显然,我缺少一些 CALayers、屏蔽甚至presentationLayer 语义的部分。

非常感谢任何指导!

I have a UIButton of the custom button type, where I just set a background and border color on the underlying CALayer of the button. I then applied a mask to this underlying layer composed of a CAShapeLayer (to get two rounded corners) as described in this post.

So far so good. I animate the UIButton to grow in size. So far so good. See below (everything in the image is the _fusedBar, save the x-axis line snippet you see below it and the dollar amount text).

fully grown UIButton referred to in code as _fusedBar

When I go to animate the UIButton to shrink using the same animation routine but different parameter values (affine translation with simultaneous frame height change), none of the UIButton (save for a sliver) is visible as the shrinking is taking place.

I've tried to have the CAShapeLayer that is the mask remove itself from its super layer, I've tried to set the mask property on the UIButton's layer to nil, etc., but none of these remove the mask such that I can see the UIButton animate (shrinking with affine translation and frame height change).

Here's the relevant animation code:

// Stackoverflow readers: Assume 'duration', 'scaledHeight' and 'delay' 
// already defined.

void (^fusedBarChange)(void) = ^{    
    _fusedBar.transform = CGAffineTransformMakeTranslation(0, -scaledHeight);
    [_fusedBar nd_setNewSizeHeight:scaledHeight];
};

[UIView animateWithDuration:duration
                      delay:delay
                    options:UIViewAnimationCurveEaseOut 
                 animations:^(void) {
                     fusedBarChange();
                 }
                 completion:^(BOOL finished) {
                     // Other stuff not relevant to _fusedBar animation
                 }];

Before this animation gets called, I have the mask setup per the post cited above. That code is below. Note that '_fusedBar' is the UIButton at the heart of this discussion.

- (void)configureRoundedTop {
    // YES: Start by creating the path (with only the top-left corner rounded)
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:_fusedBar.bounds 
                                                   byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight
                                                         cornerRadii:CGSizeMake(4.0, 4.0)];

    // Create the shape layer and set its path
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = _fusedBar.bounds;
    maskLayer.path = maskPath.CGPath;

    // Set the newly created shape layer as the mask for the image view's layer
    _fusedBar.layer.mask = maskLayer;
}

When growing the _fusedBar from a sliver to a few hundred points, the growth is animated, and you can see it.

Prior to using this CAShapeLayer mask, when shrinking the _fusedBar back to a sliver, I could see the animation (same code above, just a different value for 'scaledHeight'). Now, I cannot see the shrinking animation.

So, I know I need to somehow shake-off the effects of the masking layer before animating the shrinking operation, but the obvious things (to me) haven't worked. Here's an example of various things I've tried:

// None of these do the trick. I call them just before 
// the shrinking animation is invoked:
[_fusedBar setNeedsLayout];
[_fusedBar setNeedsDisplay];
[_fusedBar.layer.mask removeFromSuperlayer];
_fusedBar.layer.mask = nil;

Clearly, I'm missing some nugget of CALayers, masking and perhaps even presentationLayer semantics.

Any guidance much appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

假装不在乎 2024-12-14 20:48:29

几天后回过头来,我发现了我的错误(从上面发布的摘录中看不到)。

本质上,在动画放大或缩小“fusedBar”之后,我根据视图的框架重新应用蒙版。由于这将有效地与动画块一起执行,因此它将有一个视图缩小到的遮罩。

我需要将重新应用掩码代码放入动画完成块中,或者在 fusedBar 缩小时抑制它。

感谢所有看过并提供帮助的人!

Coming back to it after a couple of days, I saw my mistake (not visible from the extracts posted above).

Essentially, after the animation to grow or shrink the "fusedBar", I was reapplying a mask based on the view's frame. Since this would effectively execute in concert with the animation block, it was going to have a mask that the view was shrinking into.

I needed to put that re-apply mask code in my animation completion block or suppress it if the fusedBar was shrinking.

Thanks to all those who took a look to help out!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文