¿Formatear UILabel con viñetas?

89

¿Es posible formatear texten a UILabelpara mostrar una viñeta ?

Si es así, ¿cómo puedo hacerlo?

Robar
fuente
@Hoque: UILabels no tratan su texto como HTML.
Ben Zotto
2
¡Aquí hay una clase para esto! codeload.github.com/eyalc/ECListView/zip/master
Hemang
20
¿Por qué está cerrado como fuera de tema? Esta es una pregunta legítima con una respuesta legítima.
len
2
¿Por qué diablos esto está marcado como fuera de tema por stackoverflow.com/users/237838/andrew-barber es posiblemente un duplicado pero de ninguna manera fuera de tema?
AppHandwerker
2
Tecla de acceso directoALT+8 = •
TheTiger

Respuestas:

162

¿Quizás usar el punto de código Unicode para el carácter de viñeta en su cadena?

C objetivo

myLabel.text = @"\u2022 This is a list item!";

Rápido 4

myLabel.text = "\u{2022} This is a list item!"
Chris Doble
fuente
4
Perdona mi ignorancia pero uso UILabels todo el tiempo y me pregunto si podrías señalar un "por ejemplo".
daveMac
1
myLabel.numberOfLines = 0obtiene una etiqueta de varias líneas que respetará los caracteres de salto de línea. Aunque en general me gusta usarlo UITextFieldporque es más flexible. Por ejemplo, puede detectar fácilmente en qué carácter ha tocado un usuario cuando trabaja con un UITextField, no creo que pueda hacerlo con un UILabel. Las vistas de texto también tienen muchas otras características interesantes.
John Erck
7
Otra forma es utilizaroption+8
atulkhatri
3
Recuerde usar 'u' mayúscula si usa cadenas localizables: \ U2022
Nikolaj Nielsen
1
Swift es ligeramente diferente, "\ u {2022}"
anders
80

solo agrega " • "

Incluso yo estaba buscando algo como esto para mi textView. Lo que hice, solo agregue la cadena anterior con mi cadena y pásala a mi textView, también se puede hacer lo labelsmismo.

Respondí esto para el futuro espectador.

Zac24
fuente
• Trabajó para mi. Tenía * en Xcode. Acabo de copiar / reemplazar usando • y funcionó bien para mi Etiqueta. Reemplacé "Etiqueta" con •
Brian
46

Aquí hay una 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)

Agregar atributos de viñeta

func add(stringList: [String],
         font: UIFont,
         bullet: String = "\u{2022}",
         indentation: CGFloat = 20,
         lineSpacing: CGFloat = 2,
         paragraphSpacing: CGFloat = 12,
         textColor: UIColor = .gray,
         bulletColor: UIColor = .red) -> 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:

ingrese la descripción de la imagen aquí

Krunal
fuente
Esta es una solución muy elegante.
JeroenJK
9

En Swift 4 he usado "•" con New Line

 @IBOutlet weak var bulletLabel: UILabel!
 let arrayOfLines = ["Eat egg for protein","You should Eat Ghee","Wheat is with high fiber","Avoid to eat Fish "]
 for value in arrayOfLines {
     bulletLabel.text = bulletLabel.text!  + " • " + value + "\n"
  }

Salida:

ingrese la descripción de la imagen aquí

Jack
fuente
9
por qué evitar el pescado
rd_
7

En Swift 3.1

lblItemName.text = "\u{2022} This is a list item!"
Daxesh Nagar
fuente
3

Consulte este enlace, hice una vista personalizada para formatear texto con viñetas / otros símbolos / imagen (usando la propiedad attributeText de UILabel) como símbolo de elemento de lista (Swift 3.0) https://github.com/akshaykumarboth/SymbolTextLabel-iOS- Rápido

 import UIKit

    class ViewController: UIViewController {

    @IBOutlet var symbolView: SymbolTextLabel!

    var testString = "Understanding the concept of sales"

    var bulletSymbol = "\u{2022}" 
    var fontsize: CGFloat= 18
    override func viewDidLoad() {

        super.viewDidLoad()
         //First way // Dynamically creating SymbolTextLabel object

        let symbolTextLabel = SymbolTextLabel(frame: CGRect(x: 0, y: 0, width: 0, height: 0))

        symbolTextLabel.setText(text: testString, symbolCode: bulletSymbol) //setting text and symbol of text item

        symbolTextLabel.setFontSize(textSize: fontsize) // setting font size

        //symbolTextLabel.setSpacing(spacing: 5) // setting space between symbol and text

        self.view.addSubview(symbolTextLabel) 
//second way // from storyboard or interface builder

     symbolView.setText(text: testString, symbolCode: bulletSymbol)
 //setting text and symbol of text item 

    symbolView.setFontSize(textSize: fontsize) // setting font size

        //symbolView.setSpacing(spacing: 5) // setting space between symbol and text

         } 
    }
Akshay Kumar Ambos
fuente
2

Si también desea alinear la sangría del texto para los puntos de viñeta, puede usar el siguiente método que crea una NSAttributedStringcon las propiedades de sangría y espaciado adecuadas:

- (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;
}

Y puede usar ese método de la siguiente manera, pasando un NSArraycon los textos y siempre que ya tenga un UILabel:

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:15
                                                lineSpacing:2
                                           paragraphSpacing:10
                                                  textColor:UIColor.blackColor
                                                bulletColor:UIColor.grayColor];
Jonathan Cabrera
fuente
1

Si. Copie y pegue la siguiente viñeta: El compilador de Swift puede interpretar y mostrar la viñeta como desee dentro de Xcode, no se necesita nada más.

Reutilizar

extension String {
    static var bullet: String {
        return "• "
    }
}


print(String.bullet + "Buy apples")
let secondPoint: String = .bullet + "Buy oranges"
print(secondPoint)

salida

 Buy apples
 Buy oranges

Matriz reutilizable

extension Array where Element == String {

    var bulletList: String {
        var po = ""
        for (index, item) in self.enumerated() {
            if index != 0 {
                po += "\n"
            }
            po += .bullet + item
        }
        return po
    }
}


print(["get apples", "get oranges", "get a bannana"].bulletList)

salida

 get apples
 get oranges
 get a bannana
ScottyBlades
fuente
1
Si vota en contra. Al menos tenga la cortesía de decir por qué.
ScottyBlades
Creo que la razón se debe a que su solución no es óptima. Lo mejor es utilizar el punto de código Unicode.
Robert J. Clegg
Gracias por la atenta respuesta. ¿Por qué es mejor el punto Unicode?
ScottyBlades
Porque, si el desarrollador necesita hacer esto varias veces, en diferentes pantallas o proyectos (no en el mismo período de tiempo), se beneficiaría más al saber cuál es el valor del punto de código. Por lo tanto, no es necesario ir y multar la respuesta anterior o un lugar similar para copiarlo. Bueno, eso es lo que pienso de todos modos.
Robert J. Clegg
1
@ RobertJ.Clegg Acabo de actualizar mi respuesta para proporcionar una opción reutilizable. ¿Puede darme un ejemplo de cuándo una cadena de puntos de código hace que la viñeta sea más reutilizable que una cadena de viñetas directa?
ScottyBlades
0

Si alguien busca texto de vista de texto con viñetas como yo, a continuación se encuentra la respuesta. Por cierto, solo funciona con texto estático.

   Better experience - Refer a friend and How to Play \n Tournaments performance improvement\n UI/UX Improvements\n Critical bug fixes

He asignado el texto anterior a la vista de texto. Funcionó como estaba previsto para mí.

Narasimha Nallamsetty
fuente
0

Aquí está la solución de @krunal refactorizada en la NSAttributedStringextensión Swift 5 :

import UIKit

public extension NSAttributedString {
    static func makeBulletList(from strings: [String],
                               bulletCharacter: String = "\u{2022}",
                               bulletAttributes: [NSAttributedString.Key: Any] = [:],
                               textAttributes: [NSAttributedString.Key: Any] = [:],
                               indentation: CGFloat = 20,
                               lineSpacing: CGFloat = 1,
                               paragraphSpacing: CGFloat = 10) -> NSAttributedString
    {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.defaultTabInterval = indentation
        paragraphStyle.tabStops = [
            NSTextTab(textAlignment: .left, location: indentation)
        ]
        paragraphStyle.lineSpacing = lineSpacing
        paragraphStyle.paragraphSpacing = paragraphSpacing
        paragraphStyle.headIndent = indentation

        let bulletList = NSMutableAttributedString()

        for string in strings {
            let bulletItem = "\(bulletCharacter)\t\(string)\n"

            var attributes = textAttributes
            attributes[.paragraphStyle] = paragraphStyle

            let attributedString = NSMutableAttributedString(
                string: bulletItem, attributes: attributes
            )

            if !bulletAttributes.isEmpty {
                let bulletRange = (bulletItem as NSString).range(of: bulletCharacter)
                attributedString.addAttributes(bulletAttributes, range: bulletRange)
            }

            bulletList.append(attributedString)
        }

        if bulletList.string.hasSuffix("\n") {
            bulletList.deleteCharacters(
                in: NSRange(location: bulletList.length - 1, length: 1)
            )
        }

        return bulletList
    }
}
tadija
fuente