我正在制作一款拥有UITextView的iOS应用。当关闭该UITextView中的括号时,我想向用户突出显示它配对的左括号。到目前为止,我已经使用NSMutableAttributedString并更改了成对括号的字体大小来完成此操作,这有效但有点难看。 我真正想要的是设置动画,就像我在代码中关闭括号时xcode做同样的事情一样。 有没有办法做到这一点?
非常感谢任何帮助,虽然我对此很新,所以请不要认为我知道的太多了:)。
这是我的代码:
@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
}
}
}
正如你所看到的,我已经尝试过使用UIView.animateWithDuration来做这件事,我怀疑它没有用。
答案 0 :(得分:4)
另一个适用于我的解决方案(Swift 4)是生成多个属性字符串,将一个指定给标签,然后替换转换动画块中的内容(attributedText
)。例如:
// 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)
}
不要忘记在动画选项中使用.transitionCrossDissolve
。
答案 1 :(得分:3)
通过获取实际括号的框架并在UITextView上创建新的UILabel并为这些标签设置动画,我实现了我想要的目标。
@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
}
}
}
答案 2 :(得分:0)
有一种更简单的方法可以执行此操作,您可以在以下答案中看到: Animate text change in UILabel。
您只需要设置label.attributedText
属性即可:
UIView.transition(
with: label,
duration: 0.15,
options: .transitionCrossDissolve,
animations: {
label.attributedText = NSAttributedString(string: text, attributes: attributes)
},
completion: nil
)