CGAffineTransformMakeScale не работает - OS X - Какао

У меня есть простое приложение для 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 для моих файлов пользовательского интерфейса.

Спасибо, Дэн.

1 ответ

Решение

affineTransform собственность на CALayer это просто обертка для удобства transform имущество. На представлениях со слоями вы не должны изменять это. Это, как говорится, возможно.

Первая из ваших проблем заключается в том, что вы не можете анимировать свойства слоя, используя NSAnimation блок. Вам нужно явно создать CABasicAnimation объект, представляющий анимацию преобразования и добавляющий ее в слой. Изменить: я только что вспомнил, что на самом деле можно анимировать свойства слоя. Вам необходимо включить allowsImplicitAnimation Свойство в контексте. Назначение этого свойства - позволить вам анимировать свойства представления без использования прокси-сервера аниматора, но побочным эффектом является то, что оно позволяет вам анимировать неявные свойства слоя.

Вторая проблема, как кратко упоминалось ранее, заключается в том, что вы не можете безопасно установить точку трансформации / привязки на слое вида, если ваш вид поддерживается на слое. NSView сбросит точку трансформации и точку привязки вашего слоя при изменении геометрии. Вам разрешено изменять эти свойства, если представление является хост-слоем, но это сопровождается целым рядом проблем, которых вы, скорее всего, хотели бы избежать. Есть некоторые хаки, которые вы можете использовать, чтобы избежать этой проблемы, но они требуют мошенничества и, вероятно, их следует избегать для любых представлений, которые вам не принадлежат (например, 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).

Другие вопросы по тегам