CGAffineTransformMakeScale不工作 - OS X - Cocoa

时间:2015-04-03 09:39:26

标签: macos cocoa animation transform nsanimation

我正在开发一款简单的Mac应用程序。我希望能够在NSButton上应用变换并使其更大。两倍大小。但是我的代码不起作用,它只是将按钮滑动到一个角落。有谁知道出了什么问题?

[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {

    [numberButton1.animator.layer setAffineTransform:CGAffineTransformMakeScale(4.0, 4.0)];
    numberButton1.layer.anchorPoint = CGPointMake(0.5, 0.5);
    [numberButton1.animator.layer setAffineTransform:CGAffineTransformMakeScale(1.0, 1.0)];

} completionHandler:nil];

更新1

我尝试了以下内容,但它没有做任何事情:(

   CGAffineTransform test = CGAffineTransformMakeScale(4.0, 4.0);

   [NSAnimationContext runAnimationGroup:^(NSAnimationContext *ctx) {
        numberButton1.animator.layer.affineTransform = test;
    } completionHandler:^{
        [NSAnimationContext runAnimationGroup:^(NSAnimationContext *ctx) {
            numberButton1.animator.layer.affineTransform = CGAffineTransformIdentity;
        } completionHandler:^{
            NSLog(@"Done...");
        }];
    }];

更新2

这是我的代码sudo,希望这会有所帮助:

我的标题(.h)文件:

#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>

@interface ViewController : NSViewController {

    IBOutlet NSButton *numberButton1;
}

-(IBAction)demo:(id)sender;

@end

我的实现(.m)文件:

#import "ViewController.h"

@implementation ViewController

-(IBAction)demo:(id)sender {

    CGRect frame = numberButton1.layer.frame;
    CGPoint center = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));
    numberButton1.layer.position = center;
    numberButton1.layer.anchorPoint = CGPointMake(0.5, 0.5);

    [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {

        context.allowsImplicitAnimation = YES;
        [[NSAnimationContext currentContext] setDuration:0.2];
        numberButton1.animator.layer.affineTransform = CGAffineTransformMakeScale(4.0, 4.0);

    } completionHandler:^{

        [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {

            context.allowsImplicitAnimation = YES;
            [[NSAnimationContext currentContext] setDuration:0.2];
            numberButton1.animator.layer.affineTransform = CGAffineTransformIdentity;

        } completionHandler:nil];
    }];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view.

    numberButton1.wantsLayer = YES;
    numberButton1.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
    numberButton1.layer.backgroundColor = [NSColor colorWithRed:(17/255.0) green:(145/255.0) blue:(44/255.0) alpha:1.0].CGColor;
}

- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}

@end

我也使用Auto Layout作为我的UI文件。

谢谢,Dan。

1 个答案:

答案 0 :(得分:4)

affineTransform上的CALayer属性只是transform属性的便捷包装器。在图层支持的视图上,您​​不应该更改此设置。话虽这么说,但这是可能的。

您遇到的第一个问题是,您无法使用NSAnimation块为图层属性设置动画。您需要显式创建一个表示变换动画的CABasicAnimation对象并将其添加到图层中。 编辑:我记得实际上可以为图层属性设置动画。您需要在上下文中启用allowsImplicitAnimation属性。此属性的目的是让您在不使用动画制作代理的情况下为视图属性设置动画,但副作用是它允许您为隐式图层属性设置动画。

如前所述,第二个问题是,如果视图是图层支持的,则无法在视图的图层上安全地设置变换/锚点。只要几何体发生变化,NSView就会重置图层的变换和定位点。如果视图是图层托管,则您可以修改这些属性,但这会带来您最不希望避免的一大堆问题。您可以使用一些hacks来避免此问题,但它们需要调整,并且应该避免任何您不拥有的视图(例如NSButton)。

所以我不得不问,你为什么要把按钮的两倍大?缩放状态是短暂的,还是持久的?如果它是持久的,请改为改变框架。否则,如果它是瞬态的并且视图的几何形状没有变化,那么您可以通过修改这两个属性来逃避,因为AppKit在完成之前没有理由重置它们动画。


编辑:您没有看到动画的原因是您的原始代码在同一事务中应用了两次缩放变换。当此事务具有合并的修改时,它将选择应用的最后一个转换,这意味着它将成为身份转换,顺便说一下,应该将其写为CGAffineTransformIdentity而不是使用缩放转换。因子1.通过将另一个动画块放在第一个动画的完成块中,在新事务中应用缩小动画。例如:

[NSAnimationContext runAnimationGroup:^(NSAnimationContext *ctx) {
        ctx.allowsImplicitAnimation = YES;
        layer.affineTransform = transform;
    } completionHandler:^{
        [NSAnimationContext runAnimationGroup:^(NSAnimationContext *ctx) {
            ctx.allowsImplicitAnimation = YES;
            layer.affineTransform = CGAffineTransformIdentity;
        } completionHandler:nil];
}];

在尝试动画(wantsLayer = YES)之前,请确保要缩放的子视图的父视图是图层支持的。