Estoy escribiendo una app para iOS 7 solo y estoy tratando de conseguir decente formato de viñetas en un no-editable UITextView.

Es bastante fácil sólo tiene que insertar una viñeta de carácter, pero, por supuesto, la sangría izquierda no siga. ¿Cuál es la manera más fácil en iOS 7 para establecer una sangría izquierda después de una viñeta?

Gracias de antemano,

Frank

  • añadir pestañas antes y después de bala.
  • Me refiero a una sangría para todo el multi-línea de párrafo, no sólo la primera línea.
InformationsquelleAutor Frank R. | 2013-10-25

8 Comentarios

  1. 9

    A continuación es el código que utilizo para establecer un párrafo con viñetas. Esto viene directamente de una aplicación de trabajo y se utiliza para aplicar el estilo a todo el párrafo en respuesta a un usuario que hace clic en un botón formato. He intentado poner en todos los métodos dependientes, pero puede haber perdido algunos.

    Nota que estoy configurando la mayoría de los guiones en centímetros y por lo tanto el uso de las funciones de conversión al final de la lista.

    Yo soy también la comprobación de la presencia de un carácter de tabulación (sin ficha clave en iOS!) e insertar automáticamente un guión y una ficha.

    Si todo lo que usted necesita es el estilo de párrafo, a continuación, ver el último de los pocos métodos que a continuación donde el firstLineIndent etc ponerse en marcha.

    Nota que estas llamadas de obtener todos envueltos en [textStorage beginEditing/endEditing]. A pesar de la (IBAction) a continuación el método no está recibiendo la llamada por un objeto de interfaz de usuario directamente.

            - (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;
    }
    • Gracias por el ejemplo de código. Estoy seguro de que va a ser divertido extraer el mínimo de código, pero es muchísimo mejor que tratando de encontrar mi camino alrededor de la TextKit api doc 🙂
    • Pruebe el párr setFirstLineHeadIndent y setHeadIndent y setTabStops, usted probablemente va a requerir todos los tres juntos para crear correctamente una sangría de párrafo de viñeta. Sin embargo, tener en mente establecer el estilo de párrafo para que usted puede conseguir algunos resultados extraños si no todo.
    • Gracias por esto! FWIW, he utilizado una muy reducida versión de este para hacer una lista numerada. Básicamente, he configurado un NSTextTab con un valor de «X» (20.0 f en mi caso) y establecer mi headIndent el mismo valor. Entonces, mi cadena @»1.\t{long aquí el texto}\n2.\t{más larga de texto}». Lo tengo todo alineado perfectamente, incluso con el ajuste de línea. GRACIAS!
    • Para su INFORMACIÓN, si usted está buscando para los que se extrae el mínimo código, desplácese hacia abajo a mi respuesta: stackoverflow.com/a/26715297/1459762
  2. 45

    Lo he mirado, y he aquí que se extrae el mínimo código de Duncan respuesta para que funcione:

    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;

    Y aquí está el resultado de que en mi app:

    iOS7 TextKit: punto de alineación

  3. 8

    Esta es la solución más sencilla que he encontrado:

    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)

    la teoría que está siendo cada cadena de la matriz actúa como un «párrafo» y el estilo de párrafo consigue 0 sangría en la primera línea de la cual se obtiene una bala agregado mediante el método map.. entonces para cada línea después de que se obtiene un 10 px guión (ajustar el espaciado de la fuente métricas)

    • Bueno! Esto funcionó muy bien para mí! Gracias!
  4. 6

    Otras respuestas se basan en la configuración de la sangría de tamaño con un valor constante. Eso significa que usted tendrá que actualizar manualmente si vas a cambiar las fuentes, y no funcionará bien si usted está utilizando el Tipo de Dinámica. Afortunadamente, la medición de texto es fácil.

    Digamos que usted tiene un poco de texto y algunos atributos:

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

    Aquí es cómo medir la bala y crear un estilo de párrafo en consecuencia:

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

    Insertar esto en nuestros atributos y crear la atribuye cadena:

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

    Swift 4

    Hice una extensión para NSAttributedString que añade comodidad de inicializador de que las sangrías de los diferentes tipos de listas.

    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)
    }
    }

    Ejemplo de uso:
    iOS7 TextKit: punto de alineación

    El número de espacios después de cada viñeta, etc. no importa. El código de calcular la correspondiente sangría de ancho de forma dinámica basándose en cuántas fichas o espacios decide que después de su bala.

    Si el atribuida cadena ya tiene un estilo de párrafo, de la conveniencia de inicializador conservará las opciones de estilo de párrafo y aplicar algunas de las opciones de su propio.

    Apoyado símbolos: •, -, *, números, seguido de un período (por ejemplo, 8.)

  6. 2

    Todos ustedes pueden hacer esto mediante el uso de Atributos del Inspector,Seleccione el Campo Sangría y hacer cualquier cambio que quería hacer 🙂

    iOS7 TextKit: punto de alineación

  7. 0

    He hecho una solución swift (Swift 2.3 en el momento), basado en Lukas aplicación. Tuve un pequeño problema con las líneas que no tenía puntos de bala, así que he hecho la extensión, por lo que, opcionalmente, puede pasar de un rango para aplicar el estilo de párrafo.

    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
    }
    }
  8. 0

    Basa en thisispete‘s solución, actualizado a Swift 4.2.

    Swift 4.2

    let array = ["1st", "2nd", "3rd"]
    let textView = UITextView()
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.firstLineHeadIndent = 0
    paragraphStyle.headIndent = 12
    let bulletListText = array.map { "• \($0)" }.joined(separator: "\n")
    let attributes = [
    NSAttributedString.Key.paragraphStyle: paragraphStyle,
    NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17.0)
    ]
    textView.attributedText = NSAttributedString(string: bulletListText, attributes: attributes)

Dejar respuesta

Please enter your comment!
Please enter your name here