iOS7 TextKit: выравнивание маркеров

Я пишу приложение только для iOS 7, и я пытаюсь получить достойное форматирование на пулевых точках в не редактируемом UITextView.

Легко просто вставить символ точки пули, но, конечно, левого отступа не последует. Какой самый простой способ для iOS 7 установить левый отступ после точки маркера?

Заранее спасибо,

Фрэнк

Ниже этого кода я использую для установки маркированного абзаца. Это происходит прямо из рабочего приложения и используется для применения стиля ко всему абзацу в ответ на щелчок пользователем кнопки форматирования. Я попытался использовать все зависимые методы, но, возможно, пропустил их.

Обратите внимание, что я устанавливаю большинство отступов в сантиметрах и, следовательно, использование функций преобразования в конце списка.

Я также проверяю наличие символа табуляции (без ключа закладки на iOS!) И автоматически вставляю тире и вкладку.

Если все, что вам нужно, это стиль абзаца, тогда посмотрите на последние несколько методов, где устанавливается firstLineIndent и т. Д.

Обратите внимание, что эти вызовы все обернуты в [textStorage beginEditing/endEditing] . Несмотря на то, что (IBAction) ниже метод не получает непосредственно объект UI.

  - (IBAction) styleBullet1:(id)sender { NSRange charRange = [self rangeForUserParagraphAttributeChange]; NSTextStorage *myTextStorage = [self textStorage]; // Check for "-\t" at beginning of string and add if not found NSAttributedString *attrString = [myTextStorage attributedSubstringFromRange:charRange]; NSString *string = [attrString string]; if ([string rangeOfString:@"\t"].location == NSNotFound) { NSLog(@"string does not contain tab so insert one"); NSAttributedString * aStr = [[NSAttributedString alloc] initWithString:@"-\t"]; // Insert a bullet and tab [[self textStorage] insertAttributedString:aStr atIndex:charRange.location]; } else { NSLog(@"string contains tab"); } if ([self isEditable] && charRange.location != NSNotFound) { [myTextStorage setAttributes:[self bullet1Style] range:charRange]; } } - (NSDictionary*)bullet1Style { return [self createStyle:[self getBullet1ParagraphStyle] font:[self normalFont] fontColor:[UIColor blackColor] underlineStyle:NSUnderlineStyleNone]; } - (NSDictionary*)createStyle:(NSParagraphStyle*)paraStyle font:(UIFont*)font fontColor:(UIColor*)color underlineStyle:(int)underlineStyle { NSMutableDictionary *style = [[NSMutableDictionary alloc] init]; [style setValue:paraStyle forKey:NSParagraphStyleAttributeName]; [style setValue:font forKey:NSFontAttributeName]; [style setValue:color forKey:NSForegroundColorAttributeName]; [style setValue:[NSNumber numberWithInt: underlineStyle] forKey:NSUnderlineStyleAttributeName]; FLOG(@" font is %@", font); return style; } - (NSParagraphStyle*)getBullet1ParagraphStyle { NSMutableParagraphStyle *para; para = [self getDefaultParagraphStyle]; NSMutableArray *tabs = [[NSMutableArray alloc] init]; [tabs addObject:[[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:[self ptsFromCMF:1.0] options:nil]]; //[tabs addObject:[[NSTextTab alloc] initWithType:NSLeftTabStopType location:[self ptsFromCMF:1.0]]]; [para setTabStops:tabs]; [para setDefaultTabInterval:[self ptsFromCMF:2.0]]; [para setFirstLineHeadIndent:[self ptsFromCMF:0.0]]; //[para setHeaderLevel:0]; [para setHeadIndent:[self ptsFromCMF:1.0]]; [para setParagraphSpacing:3]; [para setParagraphSpacingBefore:3]; return para; } - (NSMutableParagraphStyle*)getDefaultParagraphStyle { NSMutableParagraphStyle *para; para = [[NSParagraphStyle defaultParagraphStyle]mutableCopy]; [para setTabStops:nil]; [para setAlignment:NSTextAlignmentLeft]; [para setBaseWritingDirection:NSWritingDirectionLeftToRight]; [para setDefaultTabInterval:[self ptsFromCMF:3.0]]; [para setFirstLineHeadIndent:0]; //[para setHeaderLevel:0]; [para setHeadIndent:0.0]; [para setHyphenationFactor:0.0]; [para setLineBreakMode:NSLineBreakByWordWrapping]; [para setLineHeightMultiple:1.0]; [para setLineSpacing:0.0]; [para setMaximumLineHeight:0]; [para setMinimumLineHeight:0]; [para setParagraphSpacing:6]; [para setParagraphSpacingBefore:3]; //[para setTabStops:<#(NSArray *)#>]; [para setTailIndent:0.0]; return para; } -(NSNumber*)ptsFromCMN:(float)cm { return [NSNumber numberWithFloat:[self ptsFromCMF:cm]]; } -(float)ptsFromCMF:(float)cm { return cm * 28.3464567; } с  - (IBAction) styleBullet1:(id)sender { NSRange charRange = [self rangeForUserParagraphAttributeChange]; NSTextStorage *myTextStorage = [self textStorage]; // Check for "-\t" at beginning of string and add if not found NSAttributedString *attrString = [myTextStorage attributedSubstringFromRange:charRange]; NSString *string = [attrString string]; if ([string rangeOfString:@"\t"].location == NSNotFound) { NSLog(@"string does not contain tab so insert one"); NSAttributedString * aStr = [[NSAttributedString alloc] initWithString:@"-\t"]; // Insert a bullet and tab [[self textStorage] insertAttributedString:aStr atIndex:charRange.location]; } else { NSLog(@"string contains tab"); } if ([self isEditable] && charRange.location != NSNotFound) { [myTextStorage setAttributes:[self bullet1Style] range:charRange]; } } - (NSDictionary*)bullet1Style { return [self createStyle:[self getBullet1ParagraphStyle] font:[self normalFont] fontColor:[UIColor blackColor] underlineStyle:NSUnderlineStyleNone]; } - (NSDictionary*)createStyle:(NSParagraphStyle*)paraStyle font:(UIFont*)font fontColor:(UIColor*)color underlineStyle:(int)underlineStyle { NSMutableDictionary *style = [[NSMutableDictionary alloc] init]; [style setValue:paraStyle forKey:NSParagraphStyleAttributeName]; [style setValue:font forKey:NSFontAttributeName]; [style setValue:color forKey:NSForegroundColorAttributeName]; [style setValue:[NSNumber numberWithInt: underlineStyle] forKey:NSUnderlineStyleAttributeName]; FLOG(@" font is %@", font); return style; } - (NSParagraphStyle*)getBullet1ParagraphStyle { NSMutableParagraphStyle *para; para = [self getDefaultParagraphStyle]; NSMutableArray *tabs = [[NSMutableArray alloc] init]; [tabs addObject:[[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:[self ptsFromCMF:1.0] options:nil]]; //[tabs addObject:[[NSTextTab alloc] initWithType:NSLeftTabStopType location:[self ptsFromCMF:1.0]]]; [para setTabStops:tabs]; [para setDefaultTabInterval:[self ptsFromCMF:2.0]]; [para setFirstLineHeadIndent:[self ptsFromCMF:0.0]]; //[para setHeaderLevel:0]; [para setHeadIndent:[self ptsFromCMF:1.0]]; [para setParagraphSpacing:3]; [para setParagraphSpacingBefore:3]; return para; } - (NSMutableParagraphStyle*)getDefaultParagraphStyle { NSMutableParagraphStyle *para; para = [[NSParagraphStyle defaultParagraphStyle]mutableCopy]; [para setTabStops:nil]; [para setAlignment:NSTextAlignmentLeft]; [para setBaseWritingDirection:NSWritingDirectionLeftToRight]; [para setDefaultTabInterval:[self ptsFromCMF:3.0]]; [para setFirstLineHeadIndent:0]; //[para setHeaderLevel:0]; [para setHeadIndent:0.0]; [para setHyphenationFactor:0.0]; [para setLineBreakMode:NSLineBreakByWordWrapping]; [para setLineHeightMultiple:1.0]; [para setLineSpacing:0.0]; [para setMaximumLineHeight:0]; [para setMinimumLineHeight:0]; [para setParagraphSpacing:6]; [para setParagraphSpacingBefore:3]; //[para setTabStops:<#(NSArray *)#>]; [para setTailIndent:0.0]; return para; } -(NSNumber*)ptsFromCMN:(float)cm { return [NSNumber numberWithFloat:[self ptsFromCMF:cm]]; } -(float)ptsFromCMF:(float)cm { return cm * 28.3464567; } 

Поэтому я огляделся, и вот извлеченный минимальный код из ответа Дункана, чтобы он работал:

 NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:yourLabel.text]; NSMutableParagraphStyle *paragrahStyle = [[NSMutableParagraphStyle alloc] init]; [paragrahStyle setParagraphSpacing:4]; [paragrahStyle setParagraphSpacingBefore:3]; [paragrahStyle setFirstLineHeadIndent:0.0f]; // First line is the one with bullet point [paragrahStyle setHeadIndent:10.5f]; // Set the indent for given bullet character and size font [attributedString addAttribute:NSParagraphStyleAttributeName value:paragrahStyle range:NSMakeRange(0, [self.descriptionLabel.text length])]; yourLabel.attributedText = attributedString; 

И вот результат этого в моем приложении:

Квадратичный мастер

Это самое простое решение, которое я нашел:

 let bulletList = UILabel() let bulletListArray = ["line 1 - enter a bunch of lorem ipsum here so it wraps to the next line", "line 2", "line 3"] let joiner = "\n" var paragraphStyle = NSMutableParagraphStyle() paragraphStyle.headIndent = 10 paragraphStyle.firstLineHeadIndent = 0 let attributes = [NSParagraphStyleAttributeName: paragraphStyle] let bulletListString = joiner.join(bulletListArray.map { "• \($0)" }) bulletList.attributedText = NSAttributedString(string: bulletListString, attributes: attributes) 

теория, являющаяся каждой строкой в ​​массиве, действует как «абзац», а стиль абзаца получает 0 отступ в первой строке, которая получает пулю, добавленную с помощью метода карты. Затем для каждой строки после нее получается отступ 10 px (отрегулируйте интервал для ваших метрик шрифтов)

Другие ответы полагаются на установку размера отступа с постоянным значением. Это означает, что вам придется вручную обновлять его, если вы меняете шрифты, и не будет работать, если вы используете Dynamic Type. К счастью, измерение текста легко.

Допустим, у вас есть текст и некоторые атрибуты:

 NSString *text = @"• Some bulleted paragraph"; UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; NSDictionary *attributes = @{NSFontAttributeName: font}; 

Вот как измерить пулю и создать стиль абзаца соответственно:

 NSString *bulletPrefix = @"• "; CGSize size = [bulletPrefix sizeWithAttributes:attributes]; NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; paragraphStyle.headIndent = size.width; 

Мы вставляем это в наши атрибуты и создаем атрибутированную строку:

 NSMutableDictionary *indentedAttributes = [attributes mutableCopy]; indentedAttributes[NSParagraphStyleAttributeName] = [paragraphStyle copy]; NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text attributes:indentedAttributes]; 

Swift 4

Я сделал расширение для NSAttributedString которое добавляет инициализатор удобства, который правильно отступы разных типов списков.

 extension NSAttributedString { convenience init(listString string: String, withFont font: UIFont) { self.init(attributedListString: NSAttributedString(string: string), withFont: font) } convenience init(attributedListString attributedString: NSAttributedString, withFont font: UIFont) { guard let regex = try? NSRegularExpression(pattern: "^(\\d+\\.|[•\\-\\*])(\\s+).+$", options: [.anchorsMatchLines]) else { fatalError() } let matches = regex.matches(in: attributedString.string, options: [], range: NSRange(location: 0, length: attributedString.string.utf16.count)) let nsString = attributedString.string as NSString let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString) for match in matches { let size = NSAttributedString( string: nsString.substring(with: match.range(at: 1)) + nsString.substring(with: match.range(at: 2)), attributes: [.font: font]).size() let indentation = ceil(size.width) let range = match.range(at: 0) let paragraphStyle = NSMutableParagraphStyle() if let style = attributedString.attribute(.paragraphStyle, at: 0, longestEffectiveRange: nil, in: range) as? NSParagraphStyle { paragraphStyle.setParagraphStyle(style) } paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: indentation, options: [:])] paragraphStyle.defaultTabInterval = indentation paragraphStyle.firstLineHeadIndent = 0 paragraphStyle.headIndent = indentation mutableAttributedString.addAttribute(.font, value: font, range: range) mutableAttributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: range) } self.init(attributedString: mutableAttributedString) } } 

Пример использования: Как используется инициализатор удобства

Количество пробелов после каждой пули и т. Д. Не имеет значения. Код будет вычислять соответствующую ширину углубления динамически в зависимости от количества вкладок или пробелов, которые вы решите иметь после пули.

Если атрибутная строка уже имеет стиль абзаца, инициализатор удобства сохранит параметры этого стиля абзаца и применит некоторые свои варианты.

Поддерживаемые символы: •, -, *, числа, за которыми следует период (например, 8.)

Вы все можете сделать это просто, используя Attributes Inspector, Select Indent Field и сделайте все, что вы хотели сделать 🙂

введите описание изображения здесь

Я сделал быстрое решение (Swift 2.3 на данный момент) на основе реализации Лукаса. У меня была небольшая проблема с линиями, у которых не было пуля, поэтому я сделал расширение, чтобы вы могли опционально передать диапазон, чтобы применить стиль абзаца.

 extension String{ func getAllignedBulletPointsMutableString(bulletPointsRange: NSRange = NSMakeRange(0, 0)) -> NSMutableAttributedString{ let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: self) let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.paragraphSpacing = 0 paragraphStyle.paragraphSpacingBefore = 0 paragraphStyle.firstLineHeadIndent = 0 paragraphStyle.headIndent = 7.5 attributedString.addAttributes([NSParagraphStyleAttributeName: paragraphStyle], range: bulletPointsRange) return attributedString } } 
Interesting Posts
Давайте будем гением компьютера.