减少NSTokenField标记的内部边距

时间:2010-11-05 01:47:25

标签: objective-c cocoa

我觉得NSTokenField中的代币有太多的内边距,即我相信两个半圆(在每一边)应该更接近文本。默认设置浪费了太多空间。

如何减少这些边距,并使令牌更紧凑?

3 个答案:

答案 0 :(得分:1)

使用Objective-C运行时,似乎有一种方法可以在不对子类进行子类化的情况下实现此目的。但是,这可能无法满足App Store的要求。

要使用Objective-C运行时,请添加

#import <objc/runtime.h>

到要对标记进行修改的文件的顶部。在此文件的类别或类别@implementation中(可能是NSTokenFieldNSTokenFieldCell上的类别),添加

static NSSize (*kOriginalCellSizeForBounds)(id, SEL, NSRect);

NSSize cellSizeForBounds_override(id self, SEL _cmd, NSRect rect)
{
    NSSize size = kOriginalCellSizeForBounds(self, _cmd, rect);
    size.width -= 10;
    return size;
}

static NSRect (*kOriginalTitleRectForBounds)(id, SEL, NSRect);

NSRect titleRectForBounds_override(id self, SEL _cmd, NSRect rect)
{
    NSRect titleRect = kOriginalTitleRectForBounds(self, _cmd, rect);
    titleRect = NSInsetRect(rect, -5, 0);
    return titleRect;
}

+ (void)load
{
    Class tokenAttachmentCellClass = objc_getClass("NSTokenAttachmentCell");

    SEL selector = @selector(cellSizeForBounds:);
    Method originalMethod = class_getInstanceMethod(tokenAttachmentCellClass, selector);
    kOriginalCellSizeForBounds = (void *)method_getImplementation(originalMethod);
    if(!class_addMethod(tokenAttachmentCellClass, selector, (IMP)cellSizeForBounds_override, method_getTypeEncoding(originalMethod))) {
        method_setImplementation(originalMethod, (IMP)cellSizeForBounds_override);
    }

    selector = @selector(titleRectForBounds:);
    originalMethod = class_getInstanceMethod(tokenAttachmentCellClass, selector);
    kOriginalTitleRectForBounds = (void *)method_getImplementation(originalMethod);
    if(!class_addMethod(tokenAttachmentCellClass, selector, (IMP)titleRectForBounds_override, method_getTypeEncoding(originalMethod))) {
        method_setImplementation(originalMethod, (IMP)titleRectForBounds_override);
    }
}

这里发生的是我们减少令牌的原始宽度(在cellSizeForBounds_override()中)并按比例增加单元格“标题”的宽度(在titleRectForBounds_override()中)。结果是具有降低的水平边距的令牌仍可在NSTokenField中正常工作。你可以修改宽度的减少量来获得你想要的效果。

您可以在Mike Ash的文章“Method Replacement for Fun and Profit”中阅读有关方法调配的更多信息;我正在使用“直接覆盖”方法调配。

答案 1 :(得分:0)

答案与此类似:How do I set the column margins in an NSTableView?

您需要子类化NSTextFieldCell并覆盖-titleRectForBounds:以传递矩形超级返回的宽度插入副本。

答案 2 :(得分:0)

我不得不对一个不属于公共API的类进行子类化。我通过BWToolkit中的BWTokenField代码了解了该怎么做。它可以工作,但我想在没有公共API的情况下这样做,因为有一天我可能想去Mac App Store。我已经提交了一份错误报告,要求公开API,他们将报告标记为重复。我并不乐观,他们会对此采取任何措施。