5

2つのを含むビューがありますNSTextFieldCell。これらのセルが描画されるサイズは、ビューのサイズから導出されます。各セルのテキストは、導出されたセルのサイズに収まる最大のものにする必要があります。フォントサイズを設定しない私が持っているものは次のとおりです。

- (void)drawRect:(NSRect)dirtyRect {
    /*
     * Observant readers will notice that I update the whole view here. If
     * there is a perceived performance problem, then I'll switch to just
     * updating the dirty rect.
     */
    NSRect boundsRect = self.bounds;
    const CGFloat monthHeight = 0.25 * boundsRect.size.height;
    NSRect monthRect = NSMakeRect(boundsRect.origin.x,
                                  boundsRect.origin.y + boundsRect.size.height
                                  - monthHeight,
                                  boundsRect.size.width,
                                  monthHeight);
    [monthCell drawWithFrame: monthRect inView: self];

    NSRect dayRect = NSMakeRect(boundsRect.origin.x,
                                boundsRect.origin.y,
                                boundsRect.size.width,
                                boundsRect.size.height - monthHeight);
    [dayCell drawWithFrame: dayRect inView: self];

    [[NSColor blackColor] set];
    [NSBezierPath strokeRect: boundsRect];
}

したがって、特定の属性に必要なサイズを文字列に要求できること、およびコンテンツに合わせてサイズを変更するようにコントロールに要求できることを知っています。どちらも当てはまらないようです。コンテンツ(この場合はセルstringValue)のサイズを既知の長方形の寸法に合わせ、それを実現するために必要な属性を不明にします。必要なサイズを見つけるにはどうすればよいですか?使用するフォントがわかっていると仮定します(使用しているため)。

更新注:文字列を切り捨てたくはありません。文字列を拡大または縮小して、提供されたrectに可能な限り最大のテキストサイズで全体が収まるようにします。

4

6 に答える 6

5

私はいくつかの同様のコードを使用しますが、さまざまなフォント、最大 10,000 のサイズを処理し、使用可能な高さとテキストが表示される領域の幅を考慮します。

#define kMaxFontSize    10000

- (CGFloat)fontSizeForAreaSize:(NSSize)areaSize withString:(NSString *)stringToSize usingFont:(NSString *)fontName;
{
    NSFont * displayFont = nil;
    NSSize stringSize = NSZeroSize;
    NSMutableDictionary * fontAttributes = [[NSMutableDictionary alloc] init];

    if (areaSize.width == 0.0 || areaSize.height == 0.0) {
        return 0.0;
    }

    NSUInteger fontLoop = 0;
    for (fontLoop = 1; fontLoop <= kMaxFontSize; fontLoop++) {
        displayFont = [[NSFontManager sharedFontManager] convertWeight:YES ofFont:[NSFont fontWithName:fontName size:fontLoop]];
        [fontAttributes setObject:displayFont forKey:NSFontAttributeName];
        stringSize = [stringToSize sizeWithAttributes:fontAttributes];

        if (stringSize.width > areaSize.width)
            break;
        if (stringSize.height > areaSize.height)
            break;
    }

    [fontAttributes release], fontAttributes = nil;

    return (CGFloat)fontLoop - 1.0;
}
于 2010-03-09T21:08:58.723 に答える
2

帯域外で、適切なサイズの二分探索を試みることが推奨されました。これはその非常に限定的な例です。

- (NSFont *)labelFontForText: (NSString *)text inRect: (NSRect)rect {
    CGFloat prevSize = 0.0, guessSize = 16.0, tempSize;
    NSFont *guessFont = nil;
    while (fabs(guessSize - prevSize) > 0.125) {
        guessFont = [NSFont labelFontOfSize: guessSize];
        NSSize textSize = [text sizeWithAttributes: 
                            [NSDictionary dictionaryWithObject: guessFont
                                                        forKey: NSFontAttributeName]];
        if (textSize.width > rect.size.width || 
            textSize.height > rect.size.height) {
            tempSize = guessSize - (guessSize - prevSize) / 2.0;
        }
        else {
            tempSize = guessSize + (guessSize - prevSize) / 2.0;
        }
        prevSize = guessSize;
        guessSize = tempSize;
    }
    return [[guessFont retain] autorelease];
}

制限 (32pt 以上のフォントや、Lucida Grande 以外のものは必要ない) は、私のニーズにとっては重要ではありませんが、この方法を使用するのをためらう人もいます。私は質問を開いたままにし、より堅牢なアプローチを受け入れます。

于 2010-03-09T16:59:32.497 に答える
1

これは、推測とチェックを行わない方法です。フォントによっては、オーバーフローを防ぐために少しパディングが必要になる場合があります (sizeWithAttributes は完全にはスケーリングされません)。ブーム!

-(float)scaleToAspectFit:(CGSize)source into:(CGSize)into padding:(float)padding
{
    return MIN((into.width-padding) / source.width, (into.height-padding) / source.height);
}

-(NSFont*)fontSizedForAreaSize:(NSSize)size withString:(NSString*)string usingFont:(NSFont*)font;
{
    NSFont* sampleFont = [NSFont fontWithDescriptor:font.fontDescriptor size:12.];//use standard size to prevent error accrual
    CGSize sampleSize = [string sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:sampleFont, NSFontAttributeName, nil]];
    float scale = [self scaleToAspectFit:sampleSize into:size padding:10];
    return [NSFont fontWithDescriptor:font.fontDescriptor size:scale * sampleFont.pointSize];
}
于 2011-09-01T23:39:52.930 に答える
0

私の場合、以下を使用します。

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{

    //Create attributes
    NSColor *text_color = nil;
    NSFont *font = [self font];
    NSString *fontName = [font fontName];
    double fontSize = [font pointSize];

    NSInteger text_size = (int) fontSize;

    if([self isHighlighted])
        text_color = [NSColor colorWithCalibratedRed:1 green:1 blue:1 alpha:1];
    else
        text_color = [NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:1];


    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSFont fontWithName:fontName size:fontSize], NSFontAttributeName,
                                text_color, NSForegroundColorAttributeName,
                                nil];


    NSAttributedString * currentText=[[NSAttributedString alloc] initWithString:[self title] attributes: attributes];

    NSSize attrSize = [currentText size];

    while (attrSize.width > cellFrame.size.width && --text_size > 0) {


        attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                      [NSFont fontWithName:fontName size:text_size], NSFontAttributeName,
                      text_color, NSForegroundColorAttributeName,
                      nil];

        currentText=[[NSAttributedString alloc] initWithString:[self title] attributes: attributes];

        attrSize = [currentText size];

    }

    switch ([self alignment]) {
        default:
        case NSLeftTextAlignment:
            [currentText drawAtPoint:NSMakePoint( cellFrame.origin.x,
                                                 cellFrame.origin.y + (cellFrame.size.height/2) - (attrSize.height/2))];
            break;

        case NSRightTextAlignment:
            [currentText drawAtPoint:NSMakePoint( cellFrame.origin.x + (cellFrame.size.width) - (attrSize.width),
                                                 cellFrame.origin.y + (cellFrame.size.height/2) - (attrSize.height/2))];
            break;

        case NSCenterTextAlignment:
            [currentText drawAtPoint:NSMakePoint( cellFrame.origin.x + (cellFrame.size.width /2) - (attrSize.width/2),
                                                 cellFrame.origin.y + (cellFrame.size.height/2) - (attrSize.height/2))];
            break;


    }




}
于 2015-09-15T16:16:48.033 に答える
0

2 つのアイデア。私が試したもの、もう1つはうまくいくかもしれません:

1) この質問のように:グラフィカルな幅に基づいて NSString を切り捨てるには? つまり、サイズが合わなくなるまで、さまざまなサイズを試してみてください。

2)セルを作成し、最大四角形を指定してテキストがセルに収まるように設定し、理想的なサイズを求めて(それを行うメソッドがあります)、セルのサイズを再度変更します。最後に、私があなたの問題を正しく理解していれば。

于 2010-03-09T16:03:41.457 に答える