改变NSWindow投影的沉重感?

时间:2015-08-25 17:43:18

标签: macos swift

我有一个有投影的NSWindow,但它是黑暗的方式。影子传播得太远,对我来说太沉重了。它是NSWindow的默认阴影,我根本没有编辑它。

我想知道的是,是否有办法缩短模糊半径或降低阴影的沉重感,使其看起来更微妙。

谢谢!

1 个答案:

答案 0 :(得分:1)

没有公共API,但您可以通过调用NSThemeFrame上的某些方法来执行此操作(这是负责窗口框架,边框等的视图类)。

这是一个例子(NSWindow的子类):

#import <objc/runtime.h>

@interface SOWindow : NSWindow
@end

@interface SOWindowThemeFrameOverrides : NSView
@end

@implementation SOWindow

+ (void)load
{
    NSArray *methodsToOverride = @[@"_shadowOffset", @"_shadowFlags", @"_shadowType"];
    for (NSString *selector in methodsToOverride) {
        Method m = class_getInstanceMethod(NSClassFromString(@"NSThemeFrame"), NSSelectorFromString(selector));
        Method m2 = class_getInstanceMethod([SOWindowThemeFrameOverrides class], NSSelectorFromString(selector));
        class_addMethod(NSClassFromString(@"NSThemeFrame"), NSSelectorFromString([NSString stringWithFormat:@"_original%@", selector]), method_getImplementation(m), method_getTypeEncoding(m));
        method_exchangeImplementations(m, m2);
    }
}

@end

@implementation SOWindowThemeFrameOverrides

- (NSSize)_shadowOffset
{
    if ([self.window isKindOfClass:[SOWindow class]]) {
        return NSMakeSize(0, 8);
    } else {
        return [self _original_shadowOffset];
    }
}

- (NSUInteger)_shadowFlags
{
    if ([self.window isKindOfClass:[SOWindow class]]) {
        return 0;
    } else {
        return [self _original_shadowFlags];
    }
}

- (NSInteger)_shadowType
{
    if ([self.window isKindOfClass:[SOWindow class]]) {
        return 4;
    } else {
        return [self _original_shadowType];
    }
}

#pragma mark Placeholder methods

- (NSSize)_original_shadowOffset
{
    // implementation will be filled in at runtime
    return NSZeroSize;
}

- (NSUInteger)_original_shadowFlags
{
    // implementation will be filled in at runtime
    return 0;
}

- (NSInteger)_original_shadowType
{
    // implementation will be filled in at runtime
    return 0;
}

@end

运行时加载SOWindow类时,将调用+ load方法。该方法通过SOWindowThemeFrameOverrides中的实现切换NSThemeFrame对3个影子方法的实现,同时将原始方法添加到具有_original前缀的类中。

当调用swizzled方法时,我们检查窗口是否为SOWindow,如果我们使用自定义阴影,如果不是我们将调用转发给原始实现。

这是我从4

返回_shadowType所得到的

SOWindow with a subtle shadow

请注意,如果您尝试将其提交给AppStore,这可能会被拒绝。