ios animation swift nsmutableattributedstring

ios - Anima un cambio en parte de un NSMutableAttributedString



animation swift (2)

Otra solución que funciona para mí (Swift 4) es generar múltiples cadenas atribuidas, asignar una a la etiqueta y luego reemplazar el contenido ( attributedText ) dentro del bloque de animación de transición. Por ejemplo:

// MARK: Extension util which generates NSAttributedString by text,font,color,backgroundColor extension NSAttributedString { class func generate(from text: String, font: UIFont = UIFont.systemFont(ofSize: 16), color: UIColor = .black, backgroundColor: UIColor = .clear) -> NSAttributedString { let atts: [NSAttributedStringKey : Any] = [.foregroundColor : color, .font : font, .backgroundColor : backgroundColor] return NSAttributedString(string: text, attributes: atts) } } // MARK: Sentence let string1 = "Hi, i''m " let string2 = "Daniel" // MARK: Generate highlighted string let prefixAttString = NSAttributedString.generate(from: string1) let highlightedSuffixAttString = NSAttributedString.generate(from: string2, backgroundColor: .red) let highlightedString = NSMutableAttributedString() highlightedString.append(prefixAttString) highlightedString.append(highlightedSuffixAttString) // MARK: Generate regular string (Same prefix, different suffix)enter image description here let regularSuffixAttString = NSAttributedString.generate(from: string2) let regularString = NSMutableAttributedString() regularString.append(prefixAttString) regularString.append(regularSuffixAttString) self.view.addSubview(label) label.attributedText = regularString // UIViewAnimationOptions.transitionCrossDissolve is necessary. UIView.transition(with: self.label, duration: 4, options: [.transitionCrossDissolve], animations: { self.label.attributedText = highlightedString }, completion: nil)

}

No olvides usar .transitionCrossDissolve en las opciones de animación.

Estoy haciendo una aplicación de iOS que tiene un UITextView. Al cerrar un paréntesis en ese UITextView, quiero resaltar al usuario con qué paréntesis de apertura se empareja. Hasta ahora he hecho esto usando un NSMutableAttributedString y cambiando el tamaño de fuente de los paréntesis emparejados, que funciona pero es algo feo. Lo que realmente quiero es animar esto de manera similar a la forma en que xcode hace lo mismo cuando cierro un paréntesis en mi código. ¿Hay alguna forma de hacer esto?

Cualquier ayuda es muy apreciada, aunque soy bastante nuevo en esto, así que no asumas que sé demasiado :)

Aquí está mi código:

@IBAction func didPressClosingParentheses(sender: AnyObject) { appendStringToInputTextView(")") var count = 1 let currentString = inputTextView.attributedText.string let characterArray = Array(currentString) let closingIndex = characterArray.count - 1 for i in reverse(0...closingIndex-1) { if characterArray[i] == "(" { count-- } else if characterArray[i] == ")" { count++ } if count == 0 { let startingIndex = i var newString = NSMutableAttributedString(string: currentString) newString.addAttribute(NSFontAttributeName, value: UIFont(name: "HelveticaNeue-Thin", size: 28)!, range: NSMakeRange(0, newString.length)) newString.addAttribute(NSForegroundColorAttributeName, value: UIColor(red: 243, green: 243, blue: 243, alpha: 1), range: NSMakeRange(0, newString.length)) newString.addAttribute(NSFontAttributeName, value: UIFont(name: "HelveticaNeue-Thin", size: 35)!, range: NSMakeRange(startingIndex, 1)) newString.addAttribute(NSFontAttributeName, value: UIFont(name: "HelveticaNeue-Thin", size: 35)!, range: NSMakeRange(closingIndex, 1)) UIView.animateWithDuration(0.4, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.8, options: nil, animations: { self.inputTextView.attributedText = newString }, nil) break } } }

Como puede ver, he intentado utilizar UIView.animateWithDuration para hacer esto, lo cual, como sospechaba, no funcionó.


Logré lo que quería obteniendo los marcos para los paréntesis reales y creando nuevos UILabels sobre mi UITextView y animando esas etiquetas.

@IBAction func didPressClosingParentheses(sender: AnyObject) { inputTextView.text = inputTextView.text + ")" var count = 1 let currentString = inputTextView.attributedText.string let characterArray = Array(currentString) let closingIndex = characterArray.count - 1 for i in reverse(0...closingIndex-1) { if characterArray[i] == "(" { count-- } else if characterArray[i] == ")" { count++ } if count == 0 { let startingIndex = i let openingRange = NSMakeRange(startingIndex, 1) let closingRange = NSMakeRange(closingIndex, 1) var openingFrame = inputTextView.layoutManager.boundingRectForGlyphRange(openingRange, inTextContainer: inputTextView.textContainer) openingFrame.origin.y += inputTextView.textContainerInset.top var openingLabel = UILabel(frame: openingFrame) openingLabel.text = "(" openingLabel.font = UIFont(name: "HelveticaNeue-Thin", size: 28) openingLabel.textColor = whiteishColor openingLabel.backgroundColor = bluishColor var closingFrame = inputTextView.layoutManager.boundingRectForGlyphRange(closingRange, inTextContainer: inputTextView.textContainer) closingFrame.origin.y += inputTextView.textContainerInset.top var closingLabel = UILabel(frame: closingFrame) closingLabel.text = ")" closingLabel.font = UIFont(name: "HelveticaNeue-Thin", size: 28) closingLabel.textColor = whiteishColor closingLabel.backgroundColor = bluishColor inputTextView.addSubview(openingLabel) inputTextView.addSubview(closingLabel) UIView.animateWithDuration(0.4, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.8, options: nil, animations: { openingLabel.transform = CGAffineTransformMakeScale(1.25, 1.25) closingLabel.transform = CGAffineTransformMakeScale(1.25, 1.25) }, nil) UIView.animateWithDuration(0.4, delay: 0.2, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.8, options: nil, animations: { openingLabel.transform = CGAffineTransformMakeScale(1.0, 1.0) closingLabel.transform = CGAffineTransformMakeScale(1.0, 1.0) }, nil) UIView.animateWithDuration(0.25, delay: 0.4, options: nil, animations: { openingLabel.alpha = 0 closingLabel.alpha = 0 }, completion: { finished in openingLabel.removeFromSuperview() closingLabel.removeFromSuperview() }) break } } }