Can IKImageBrowserView display multi-line titles?

2.3k views Asked by At

I'd like my IKImageBrowserView to display long titles by wrapping them and displaying them in multiple lines, but I've been unable to achieve this.

I've tried changing the size of the titleFrame returned in the ImageBrowserCell subclass and also setting the paragraph style on the title so that it should wrap (NSLineBreakByWordWrapping) but I only ever get a single line of text.

Has anyone tried this? Any other suggestion I might try?

1

There are 1 answers

3
dvs On

Not easily, I'm afraid. One way you can do it is by leaving imageTitle blank and drawing text on a CALayer. I was able to make it work with fairly decent results:

enter image description here

First things first -- since you're not going to be using the standard imageTitle property, you want to create a new title property in your <IKImageBrowserItem>-conforming data object. I called mine simply title.

Then, you want to create an IKImageBrowserCell subclass. Make sure to tell your IKImageBrowserView you're using a custom cell; I just wrote a quick category for this:

@implementation IKImageBrowserView(CustomCell)
- (IKImageBrowserCell *)newCellForRepresentedItem:(id)cell
{
    return [[MyCustomImageBrowserCell alloc] init];
}
@end

Next, in your custom cell, override the method - (CALayer *)layerForType:(NSString *)type. Create and return a CALayer for a specific layer location type:

- (CALayer *)layerForType:(NSString *)type
{    
    if( [type isEqualToString:IKImageBrowserCellBackgroundLayer] )
    {       
        CALayer *layer = [CALayer layer];
        layer.delegate = self;
        layer.frame = self.frame; // the cell's frame
        layer.name = type; // a way to refer to the layer location type during drawing if need be
        [layer setNeedsDisplay];
        return layer;
    }

    return [super layerForType:type];
}

Then, implement the -drawLayer:inContext: method in your custom cell to handle the layer's drawing:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    // Set the current context.
    [NSGraphicsContext saveGraphicsState];
    NSGraphicsContext *nscg = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO];
    [NSGraphicsContext setCurrentContext:nscg];

    NSString *title = [self.representedItem title];

    // Wrap and center the text
    NSMutableParagraphStyle *paragraphStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
    [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
    [paragraphStyle setAlignment:NSCenterTextAlignment];

    NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
    [attrs setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
    [attrs setObject:[NSFont systemFontOfSize:12.0f] forKey:NSFontAttributeName];

    CGFloat padding = 4.0f;

    [title drawInRect:NSMakeRect(
        0, 
        -(self.imageFrame.size.height + padding), 
        self.frame.size.width, 
        100
    ) withAttributes:attrs];

    [NSGraphicsContext restoreGraphicsState];
}

Unfortunately, this approach does have a few drawbacks. The text doesn't get a blue selection background like imageTitle does. You can, however, draw your own selection background using an NSBezierPath inside a custom CALayer for the IKImageBrowserCellSelectionLayer.

Hope this is enough to go on.