1

我想在我的 Mac 应用程序中为按钮的宽度设置动画,同时有一个背景图像和一个前景图像。为此,我使用了@kgn 很棒的库 BBlock ( https://github.com/kgn/BBlock )。

问题是背景图像似乎被画在一个后面,所以当按钮缩小时,你甚至看不到背景图像动画,它似乎被切断了。 按钮图像切断

如果我只使用 setImage,这种“动画化”宽度变化的方式是有效的,但是我没有得到背景图像的好处。

我制作了一个自定义按钮,可以逐步缩放按钮(基本上是动画)。它每次运行都会将按钮的大小更改一个像素,并将图像、背景图像和备用背景图像也更改一个像素:

- (void)scaleTestButtonUntilWidth:(int)width{
    [NSTimer scheduledTimerRepeats:YES withTimeInterval:timeInterval andBlock:^{
        if (self.width == width) {
            return;
        }

        int newSize;
        if (width > self.width) {
            newSize = self.width += 1;
        }else if (width < self.width){
            newSize = self.width -= 1;
        }

        self.width = newSize;
        [self setImage:self.image];
        [self setAlternateBackgroundImage:[self alternateBGImage]];
        [self setBackgroundImage:[self BGImage]];
    }];
}

setBackgroundImage 看起来像这样,setAlternateBackgroundImage 的实现是相同的:

- (void)setBackgroundImage:(NSImage *)backgroundImage{
    [self setImage:[self imageWithBackgroundImage:backgroundImage
                                          andIcon:self.image]];
    [self setButtonType:NSMomentaryChangeButton];
    [self setBordered:NO];
}

它调用实​​际绘制图像的方法:

- (NSImage *)imageWithBackgroundImage:(NSImage *)background andIcon:(NSImage *)icon{
    return [NSImage imageForSize:background.size withDrawingBlock:^{
        NSRect bounds = NSZeroRect;
        bounds.size = background.size;

        NSRect iconRect = NSZeroRect;
        iconRect.size = icon.size;
        iconRect.origin.x = round(background.size.width*0.5f-iconRect.size.width*0.5f);
        iconRect.origin.y = round(background.size.height*0.5f-iconRect.size.height*0.5f);

        [background drawInRect:bounds fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
        [icon drawInRect:iconRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
    }];
} 

借助此方法:

+ (NSImage *)imageForSize:(NSSize)size withDrawingBlock:(void(^)())drawingBlock{
    if(size.width <= 0 || size.width <= 0){
        return nil;
    }

    NSImage *image = [[NSImage alloc] initWithSize:size];

    [image lockFocus];
    drawingBlock();
    [image unlockFocus];
#if !__has_feature(objc_arc)
    return [image autorelease];
#else
    return image;
#endif
}
4

2 回答 2

0

也许尝试保存和恢复图形上下文。

return [NSImage imageForSize:background.size withDrawingBlock:^{
    NSRect bounds = NSZeroRect;
    bounds.size = background.size;

    NSRect iconRect = NSZeroRect;
    iconRect.size = icon.size;
    iconRect.origin.x = round(background.size.width*0.5f-iconRect.size.width*0.5f);
    iconRect.origin.y = round(background.size.height*0.5f-iconRect.size.height*0.5f);

    CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
    CGContextSaveGState(context);        
    [background drawInRect:bounds fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
    [icon drawInRect:iconRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
    CGContextRestoreGState(context);
}];
于 2013-02-20T21:37:55.323 回答
0

我想知道你是否会更好地继承 NSButton 并覆盖drawRect

于 2013-02-22T21:59:48.847 回答