ios objective-c swift nsattributedstring bulletedlist

ios - ¿NSAttributedString insertando un punto de bala?



objective-c swift (6)

Así que tengo una NSAttributedString que quiero insertar un bullet point al principio de una parte del texto. ¿Cómo puedo hacer esto? ¿Cómo creo un estilo CTPAragraphStyle que crea este punto de viñeta cuando CTPAragraphStyle el texto?

Edición: Debería estar disponible en iOS


Aquí está la buena solución con Swift

let label = UILabel() label.frame = CGRect(x: 40, y: 100, width: 280, height: 600) label.textColor = UIColor.lightGray label.numberOfLines = 0 let arrayString = [ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." ] label.attributedText = add(stringList: arrayString, font: label.font, bullet: "") self.view.addSubview(label)

Añadir atributos de viñeta

Swift 4.2 ++

func add(stringList: [String], font: UIFont, bullet: String = "/u{2022}", indentation: CGFloat = 20, lineSpacing: CGFloat = 2, paragraphSpacing: CGFloat = 12, textColor: UIColor = .gray, bulletColor: UIColor = .green) -> NSAttributedString { let textAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: textColor] let bulletAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: bulletColor] let paragraphStyle = NSMutableParagraphStyle() let nonOptions = [NSTextTab.OptionKey: Any]() paragraphStyle.tabStops = [ NSTextTab(textAlignment: .left, location: indentation, options: nonOptions)] paragraphStyle.defaultTabInterval = indentation //paragraphStyle.firstLineHeadIndent = 0 //paragraphStyle.headIndent = 20 //paragraphStyle.tailIndent = 1 paragraphStyle.lineSpacing = lineSpacing paragraphStyle.paragraphSpacing = paragraphSpacing paragraphStyle.headIndent = indentation let bulletList = NSMutableAttributedString() for string in stringList { let formattedString = "/(bullet)/t/(string)/n" let attributedString = NSMutableAttributedString(string: formattedString) attributedString.addAttributes( [NSAttributedString.Key.paragraphStyle : paragraphStyle], range: NSMakeRange(0, attributedString.length)) attributedString.addAttributes( textAttributes, range: NSMakeRange(0, attributedString.length)) let string:NSString = NSString(string: formattedString) let rangeForBullet:NSRange = string.range(of: bullet) attributedString.addAttributes(bulletAttributes, range: rangeForBullet) bulletList.append(attributedString) } return bulletList }

Swift 4.0 y 4.1

func add(stringList: [String], font: UIFont, bullet: String = "/u{2022}", indentation: CGFloat = 20, lineSpacing: CGFloat = 2, paragraphSpacing: CGFloat = 12, textColor: UIColor = .gray, bulletColor: UIColor = .green) -> NSAttributedString { let textAttributes: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: font, NSAttributedStringKey.foregroundColor: textColor] let bulletAttributes: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: font, NSAttributedStringKey.foregroundColor: bulletColor] let paragraphStyle = NSMutableParagraphStyle() let nonOptions = [NSTextTab.OptionKey: Any]() paragraphStyle.tabStops = [ NSTextTab(textAlignment: .left, location: indentation, options: nonOptions)] paragraphStyle.defaultTabInterval = indentation //paragraphStyle.firstLineHeadIndent = 0 //paragraphStyle.headIndent = 20 //paragraphStyle.tailIndent = 1 paragraphStyle.lineSpacing = lineSpacing paragraphStyle.paragraphSpacing = paragraphSpacing paragraphStyle.headIndent = indentation let bulletList = NSMutableAttributedString() for string in stringList { let formattedString = "/(bullet)/t/(string)/n" let attributedString = NSMutableAttributedString(string: formattedString) attributedString.addAttributes( [NSAttributedStringKey.paragraphStyle : paragraphStyle], range: NSMakeRange(0, attributedString.length)) attributedString.addAttributes( textAttributes, range: NSMakeRange(0, attributedString.length)) let string:NSString = NSString(string: formattedString) let rangeForBullet:NSRange = string.range(of: bullet) attributedString.addAttributes(bulletAttributes, range: rangeForBullet) bulletList.append(attributedString) } return bulletList }

Aquí está el resultado:


Aquí está la excelente respuesta de Krunal en Objective-C . También elimina el espacio entre párrafos en el último elemento de la viñeta para evitar el relleno inferior adicional en el UILabel.

UILabel *label = [UILabel new]; label.frame = CGRectMake(40, 100, 280, 600); label.textColor = UIColor.lightGrayColor; label.numberOfLines = 0; NSArray *stringArray = @[@"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", @"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", @"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", @"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." ]; label.attributedText = [self attributedStringForBulletTexts:stringArray withFont:label.font bulletString:@"" indentation:20 lineSpacing:2 paragraphSpacing:12 textColor:UIColor.grayColor bulletColor:UIColor.greenColor];

Y aquí está la función que crea el texto atribuido real:

- (NSAttributedString *)attributedStringForBulletTexts:(NSArray *)stringList withFont:(UIFont *)font bulletString:(NSString *)bullet indentation:(CGFloat)indentation lineSpacing:(CGFloat)lineSpacing paragraphSpacing:(CGFloat)paragraphSpacing textColor:(UIColor *)textColor bulletColor:(UIColor *)bulletColor { NSDictionary *textAttributes = @{NSFontAttributeName: font, NSForegroundColorAttributeName: textColor}; NSDictionary *bulletAttributes = @{NSFontAttributeName: font, NSForegroundColorAttributeName: bulletColor}; NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; paragraphStyle.tabStops = @[[[NSTextTab alloc] initWithTextAlignment: NSTextAlignmentLeft location:indentation options:@{}]]; paragraphStyle.defaultTabInterval = indentation; paragraphStyle.lineSpacing = lineSpacing; paragraphStyle.paragraphSpacing = paragraphSpacing; paragraphStyle.headIndent = indentation; NSMutableAttributedString *bulletList = [NSMutableAttributedString new]; for (NSString *string in stringList) { NSString *formattedString = [NSString stringWithFormat:@"%@/t%@/n", bullet, string]; NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:formattedString]; if (string == stringList.lastObject) { paragraphStyle = [paragraphStyle mutableCopy]; paragraphStyle.paragraphSpacing = 0; } [attributedString addAttributes:@{NSParagraphStyleAttributeName: paragraphStyle} range:NSMakeRange(0, attributedString.length)]; [attributedString addAttributes:textAttributes range:NSMakeRange(0, attributedString.length)]; NSRange rangeForBullet = [formattedString rangeOfString:bullet]; [attributedString addAttributes:bulletAttributes range:rangeForBullet]; [bulletList appendAttributedString:attributedString]; } return bulletList; }


Aquí hay un enfoque más moderno que funciona desde iOS6:

NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:@"•/texample bullet fill out the text to check what happens on the second line and make sure it is lining up OK"]; NSMutableParagraphStyle *paragraphStyle; paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; [paragraphStyle setTabStops:@[[[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:15 options:nil]]]; [paragraphStyle setDefaultTabInterval:15]; [paragraphStyle setFirstLineHeadIndent:0]; [paragraphStyle setHeadIndent:15]; [string addAttributes:@{NSParagraphStyleAttributeName: paragraphStyle} range:NSMakeRange(0,[string length])];


El bit fácil: [mutableAttributedString insertAttributedString: @ "• / t" atIndex: 0];

La parte dura. Algo a lo largo de las siguientes líneas. (Esto se extrae de un proyecto más grande, pero puede darle un comienzo decente).

NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:@"•/texample bullet fill out the text to check what happens on the second line and make sure it is lining up OK"]; CTTextAlignment alignment = kCTLeftTextAlignment; CGFloat paragraphSpacing = 0.0; CGFloat paragraphSpacingBefore = 0.0; CGFloat firstLineHeadIndent = 15.0; CGFloat headIndent = 30.0; CGFloat firstTabStop = 15.0; // width of your indent CGFloat lineSpacing = 0.45; CTTextTabRef tabArray[] = { CTTextTabCreate(0, firstTabStop, NULL) }; CFArrayRef tabStops = CFArrayCreate( kCFAllocatorDefault, (const void**) tabArray, 1, &kCFTypeArrayCallBacks ); CFRelease(tabArray[0]); CTParagraphStyleSetting altSettings[] = { { kCTParagraphStyleSpecifierLineSpacing, sizeof(CGFloat), &lineSpacing}, { kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment}, { kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(CGFloat), &firstLineHeadIndent}, { kCTParagraphStyleSpecifierHeadIndent, sizeof(CGFloat), &headIndent}, { kCTParagraphStyleSpecifierTabStops, sizeof(CFArrayRef), &tabStops}, { kCTParagraphStyleSpecifierParagraphSpacing, sizeof(CGFloat), &paragraphSpacing}, { kCTParagraphStyleSpecifierParagraphSpacingBefore, sizeof(CGFloat), &paragraphSpacingBefore} }; CTParagraphStyleRef style; style = CTParagraphStyleCreate( altSettings, sizeof(altSettings) / sizeof(CTParagraphStyleSetting) ); if ( style == NULL ) { NSLog(@"*** Unable To Create CTParagraphStyle in apply paragraph formatting" ); return; } [string addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:(NSObject*)style,(NSString*) kCTParagraphStyleAttributeName, nil] range:NSMakeRange(0,[string length])]; CFRelease(tabStops); CFRelease(style);

Debe incluir el marco CoreText y luego importar CoreText / CoreText.h


No es la respuesta real para esta pregunta, pero esto puede ayudar.

solo agrega " • "

Incluso estaba buscando algo como esto para mi textView. Lo que hice, solo agregue la cadena anterior con mi cadena y pásela a mi textView, lo mismo se puede hacer para las etiquetas también. Respondí esto para el futuro espectador.


No implementas una lista con viñetas con un estilo de párrafo en iOS. Establezca sus tabulaciones como desee y luego inserte una pestaña, viñeta, pestaña al comienzo del párrafo.

CTParagraphStyle es bastante inflexible, por lo que no puede simplemente agregarle nuevos estilos de su elección. Sin embargo, puede agregar cualquier atributo que desee ( MYBulletStyle ) a ejecuciones arbitrarias dentro de NSAttributedString . Esto puede ser útil para pasar la información de la lista de viñetas con NSAttributedString y luego reconstruir la cadena para incluir las viñetas cuando esté listo para mostrarla. Pero Core Text no procesará las balas automáticamente.