程序化地向NSTextView添加带项目符号的列表的两种方法:
方法1:
以下链接引导我找到了第一种方法,但除非您想使用某些特殊的非Unicode符号作为项目符号,否则这是不必要的绕路:
这需要:(1)一个替换任意字符的子类布局管理器来代替项目符号;和(2)一个具有firstLineHeadIndent、略微大于该缩进的制表位和用于合并两者的换行的headIndent的段落样式。
布局管理器如下:
#import <Foundation/Foundation.h>
@interface TickerLayoutManager : NSLayoutManager {
NSFont *fontNormal;
NSFont *fontIndent;
NSFont *fontBold;
NSGlyph glyphBullet;
CGFloat fWidthGlyphPlusSpace;
}
@property (nonatomic, retain) NSFont *fontNormal;
@property (nonatomic, retain) NSFont *fontIndent;
@property (nonatomic, retain) NSFont *fontBold;
@property NSGlyph glyphBullet;
@property CGFloat fWidthGlyphPlusSpace;
@end
#import "TickerLayoutManager.h"
@implementation TickerLayoutManager
@synthesize fontNormal;
@synthesize fontIndent;
@synthesize fontBold;
@synthesize glyphBullet;
@synthesize fWidthGlyphPlusSpace;
- (id)init {
self = [super init];
if (self) {
self.fontNormal = [NSFont fontWithName:@"Baskerville" size:14.0f];
self.fontIndent = [NSFont fontWithName:@"Baskerville" size:12.0f];
self.fontBold = [NSFont fontWithName:@"Baskerville Bold" size:14.0f];
self.glyphBullet = [self.fontIndent glyphWithName:@"bullet"];
NSBezierPath *bezierPath = [NSBezierPath bezierPath];
[bezierPath moveToPoint:NSMakePoint(0.0f, 0.0f)];
[bezierPath appendBezierPathWithGlyph:self.glyphBullet inFont:self.fontIndent];
NSRect rectGlyphOutline = [bezierPath bounds];
NSSize sizeSpace = [@" " sizeWithAttributes:[NSDictionary dictionaryWithObject:self.fontIndent forKey:NSFontAttributeName]];
self.fWidthGlyphPlusSpace = rectGlyphOutline.size.width + sizeSpace.width;
self.fWidthGlyphPlusSpace *= 1.5;
}
return self;
}
- (void)drawGlyphsForGlyphRange:(NSRange)range
atPoint:(NSPoint)origin {
printf("\nCalling TickerLayoutManager's drawGlyphs method.");
NSString *string = [[self textStorage] string];
for (int i = range.location; i < range.length; i++) {
if ([string characterAtIndex:i] == '>')
[self replaceGlyphAtIndex:i withGlyph:self.glyphBullet];
}
[super drawGlyphsForGlyphRange:range atPoint:origin];
}
@end
在您的窗口/视图控制器的 awakeFromNib 方法中,将布局管理器分配给文本视图,如下所示:
- (void) awakeFromNib {
TickerLayoutManager *newLayoutMgr = [[TickerLayoutManager alloc] init];
NSTextContainer *textContainer = [self.txvProgressTicker textContainer];
[textContainer replaceLayoutManager:newLayoutMgr];
[newLayoutMgr release];
}
然后添加一个类似于这样的方法:
- (void) addProgressTickerLine:(NSString *)string
inStyle:(uint8_t)uiStyle {
if (!string)
return;
NSFont *font = nil;
TickerLayoutManager *tickerLayoutMgr = (TickerLayoutManager *)[self.txvProgressTicker layoutManager];
switch (uiStyle) {
case kTickerStyleNormal:
font = tickerLayoutMgr.fontNormal;
break;
case kTickerStyleIndent:
font = tickerLayoutMgr.fontIndent;
break;
case kTickerStyleBold:
font = tickerLayoutMgr.fontBold;
break;
default:
font = tickerLayoutMgr.fontNormal;
break;
}
NSMutableParagraphStyle *paragStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[paragStyle setAlignment:NSLeftTextAlignment];
if (uiStyle == kTickerStyleIndent) {
string = [@"\n>\t" stringByAppendingString:string];
[paragStyle setFirstLineHeadIndent:15.0f];
NSTextTab *textTabFllwgBullet = [[NSTextTab alloc] initWithType:NSLeftTabStopType location:15.0f + tickerLayoutMgr.fWidthGlyphPlusSpace];
[paragStyle setTabStops:[NSArray arrayWithObject:textTabFllwgBullet]];
[textTabFllwgBullet release];
[paragStyle setHeadIndent:15.0f + tickerLayoutMgr.fWidthGlyphPlusSpace];
}
else {
string = [@"\n" stringByAppendingString:string];
}
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
font, NSFontAttributeName,
paragStyle, NSParagraphStyleAttributeName,
nil];
NSAttributedString *attrs = [[NSAttributedString alloc] initWithString:string attributes:dict];
[[self.txvProgressTicker textStorage] appendAttributedString:attrs];
[attrs release];
[paragStyle release];
}
测试一下:
NSString *sTicker = NSLocalizedString(@"First normal line of ticker should wrap to left margin", @"First normal line of ticker should wrap to left margin");
[self addProgressTickerLine:sTicker inStyle:kTickerStyleNormal];
sTicker = NSLocalizedString(@"Indented ticker line should have bullet point and should wrap farther to right.", @"Indented ticker line should have bullet point and should wrap farther to right.");
[self addProgressTickerLine:sTicker inStyle:kTickerStyleIndent];
sTicker = NSLocalizedString(@"Try a second indented line, to make sure both line up.", @"Try a second indented line, to make sure both line up.");
[self addProgressTickerLine:sTicker inStyle:kTickerStyleIndent];
sTicker = NSLocalizedString(@"Final bold line", @"Final bold line");
[self addProgressTickerLine:sTicker inStyle:kTickerStyleBold];
你得到这个:
![enter image description here](https://istack.dev59.com/aQiG0.webp)
方法2:
但是,子弹符号是一个普通的Unicode字符,十六进制为2022。因此,您可以直接将其放入字符串中,并获得精确的测量结果,如下所示:
NSString *stringWithGlyph = [NSString stringWithUTF8String:"\u2022"];
NSString *stringWithGlyphPlusSpace = [stringWithGlyph stringByAppendingString:@" "];
NSSize sizeGlyphPlusSpace = [stringWithGlyphPlusSpace sizeWithAttributes:[NSDictionary dictionaryWithObject:self.fontIndent forKey:NSFontAttributeName]];
self.fWidthGlyphPlusSpace = sizeGlyphPlusSpace.width;
因此,不需要自定义布局管理器。只需将paragStyle缩进设置为上述内容,并将文本字符串附加到包含回车符+项目符号字符+空格(或+制表符,在这种情况下,您仍然需要该制表符停止)的字符串中即可。
使用空格,这将产生更紧凑的结果:
![enter image description here](https://istack.dev59.com/wdQ0E.webp)
想要使用除了圆点以外的符号吗?这里有一个不错的Unicode表格:http://www.danshort.com/unicode/