【问题标题】:How to animate a CALayer attached to UIImageView?如何为附加到 UIImageView 的 CALayer 设置动画?
【发布时间】:2012-11-01 10:31:57
【问题描述】:

我正在使用 Bartosz 提出的 code 向 UIImageView 添加蒙版。它工作正常。

#import <QuartzCore/QuartzCore.h>

CALayer *mask = [CALayer layer];
mask.contents = (id)[[UIImage imageNamed:@"mask.png"] CGImage];
mask.frame = CGRectMake(0, 0, 320.0, 100.0);
yourImageView.layer.mask = mask;
yourImageView.layer.masksToBounds = YES;

此外,我想为面具设置动画,例如向右滑动遮罩,以便在动画结束时,遮罩不再应用于 UIImageView。

在我的特定情况下,蒙版使用完全透明的图像,因此 UIImageView 在初始状态下不可见(工作正常),但预计在动画结束时会如此。但是,如果需要对蒙版进行动画处理,该想法可能会重复用于任何其他用例。

这个想法是操纵蒙版框架的 x 原点部分。所以,我想出了这个代码:

[UIView animateWithDuration: 0.2
                      delay: 0
                    options: UIViewAnimationCurveEaseInOut
                 animations:^{
                         CGRect maskFrame = yourImageView.layer.mask.frame;
                         maskFrame.origin.x = 320.0;
                         yourImageView.layer.mask.frame = maskFrame;
                     }
                 completion:^(BOOL finished){}];

不幸的是,遮罩是随时应用于整个 UIImageView 的,它不会向右滑动。

更新 1:

这是我实际使用的设置视图和掩码的代码:它是一个 UITableViewCell。

APPCell.m(APPCell.h“扩展”UITableViewCell)

#import "APPCell.h"
#import <QuartzCore/QuartzCore.h>

@interface APPCell()
@property (strong, nonatomic) UIImageView *menu;
@property (strong, nonatomic) CALayer *menuMask;
...
@end

@implementation APPCell
...

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self.menu = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320.0, 88.0)];
[self.menu setBackgroundColor:[UIColor clearColor]];
[self.menu setImage:[UIImage imageNamed:@"cell_back"]];
[self addSubview:self.menu];

self.menuMask = [CALayer layer];
self.menuMask.contents = (id)[[UIImage imageNamed:@"cell_mask"] CGImage];
self.menuMask.frame = CGRectMake(0, 0, 320.0, 88.0);
self.menu.layer.mask = self.menuMask;
self.menu.layer.masksToBounds = YES;
}
...

我现在不是借助 UIKit 来制作动画,而是使用 CoreAnimation 的隐式动画来移动遮罩层:

APPCell.m

...
- (void)swipeLeft
{
self.menuMask.position = CGPointMake(-320.0, 0.0);
}
...

我可以确认调用了 swipeLeft。我希望面具“消失”并看到 [UIImage imageNamed:@"cell_back"]],当我取消注释 self.menu.layer.mask = self.菜单掩码

解决方案:

我没有在 CALayer 上设置内容,而是将背景颜色设置为白色。这是我正在使用的代码:

self.menuSubMenuMask = [CALayer layer];
self.menuSubMenuMask.backgroundColor = [[UIColor whiteColor] CGColor];
self.menuSubMenuMask.frame = CGRectMake(320.0, 0.0, 320.0, 88.0);
self.tableCellSubMenu.layer.mask = self.menuSubMenuMask;
self.tableCellSubMenu.layer.masksToBounds = YES;

为了显示应用了 CALayer 的 UIImageView,CALayer 不能位于 UIImageView 的“上方”。

【问题讨论】:

  • 大概你的意思是maskFrame = imageView.layer.mask.frame; 和下面的预期反向两行?
  • Tommy,是的,谢谢,你是对的,我更新了它,但不幸的是,这只是一个特定的错字,因此并不能解决问题

标签: objective-c ios uiview uiimageview


【解决方案1】:

使用 UIViews 的 UIKit 动画比直接使用 Core Animation 受限得多。特别是你试图动画的不是 UIView 的动画属性之一。此外,正如View Programming Guide for iOS 中所阐明的那样:

注意:如果您的视图托管自定义图层对象(即没有关联视图的图层对象),您必须使用 Core Animation 对它们的任何更改进行动画处理。

在您的示例中就是这种情况。您已将 CALayer 添加到您的视图中,UIKit 将无法为您制作动画效果。另一方面,您可以直接使用 Core Animation 为遮罩层的运动设置动画。您应该能够使用 Core Animation Programming Guide 中描述的隐式动画轻松完成此操作。请注意,从CALayer Animatable Properties 的列表中,该帧是不可动画的。相反,您应该使用position

【讨论】:

  • 感谢 Torrey,您所说的完全有道理,文档也证明了这一点。不幸的是,我仍然无法让它工作。我现在使用“self.menuMask.position = CGPointMake(-320.0, 0.0);”将遮罩层向左移动。我添加了我在上一篇文章中使用的其他代码。
  • 当您使用self.menuMask.position = CGPointMake(-320.0, 0.0) 制作移动蒙版的动画时,您是否发现有任何变化?请注意,这并不是您想要的,因为position 是 CALayer 的中心点。所以要完全把它移开,你会想要self.menuMask.position = CGPointMake(-320.0-44.0, 0.0)。如果一切正常,您仍然应该能够从动画中看到一些效果。
  • 什么都没有,没有动画。我假设设置“self.menuMask.frame = CGRectMake(0, 0, 320.0, 88.0);”导致掩码大小为 320.0 x 88.0,因此我假设“self.menuMask.position = CGPointMake(-320.0, 0.0);”应该这样做。但无论如何,根本没有明显的变化。
  • (Doh!是的,当然,您的位置变化肯定会将图层移开。)如果隐式动画不适合您,您应该尝试显式动画。这样做的好处是更容易调试,因为您可以从CAAnimation 委托看到动画何时开始和结束。 Apple Tech QA1620 提供了有关如何使用显式动画为 CALayer 位置设置动画的示例代码。
  • 虽然这个答案并没有真正解决我的问题(我在其他地方犯了一个错误,所以在上面),我接受了这个作为答案,因为你提供了 Apple Tech QA1620 链接,这可能有助于其他人。
【解决方案2】:

您可以使用CATransition 实现您想要的目标,尽管这可能不是您想要的解决方案:

1) 首先,像之前一样为图层设置蒙版

2) 当您想移除遮罩并显示您的图像时,请使用以下代码:

CATransition* transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
transition.duration = 1.0;
[mask addAnimation:transition forKey:kCATransition];
imageView.layer.mask.contents = [UIImage imageNamed:@"black.png"].CGImage;

这里的主要技巧 - 我们为遮罩层创建了过渡动画,因此当您更改遮罩层的任何(我不确定)属性时,将应用此动画。现在我们将遮罩的内容设置为完全黑色的图像以完全移除遮罩 - 现在我们有了平滑的推动动画,我们的遮罩图像向左移动,而未遮罩的图像进入它的位置

【讨论】:

  • 使用黑色图像也可以。但是,我使用的是白色。无论如何,这两种方法都有效。
【解决方案3】:

最简单的方法是使用 CoreAnimation 本身:

CGPoint fromPoint = mask.position;
CGPoint toPoint = CGPointMake(fromPoint.x*3.0, fromPoint.y);

mask.position = toPoint; // CoreAnimation animations do *not* persist

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue = [NSValue valueWithCGPoint:fromPoint];
animation.toValue = [NSValue valueWithCGPoint:toPoint];
animation.duration = 4.0f;

[mask addAnimation:animation forKey:@"position"];

【讨论】:

    猜你喜欢
    • 2019-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    相关资源
    最近更新 更多