简体   繁体   English

动画 NSMutableAttributedString 的部分更改

[英]Animate a change in part of an NSMutableAttributedString

I'm making an iOS app that has a UITextView.我正在制作一个具有 UITextView 的 iOS 应用程序。 When closing a parenthesis in that UITextView, I want to highlight to the user which opening parenthesis it pairs to.在该 UITextView 中关闭括号时,我想向用户突出显示它与哪个左括号配对。 So far I've done this using an NSMutableAttributedString and changing the font size of the paired parentheses, which works but is kind of ugly.到目前为止,我已经使用 NSMutableAttributedString 并更改了成对括号的字体大小来完成此操作,这可行但有点难看。 What I really want is to animate this similarly to the way xcode does the same thing when I close a parenthesis in my code.我真正想要的是在我的代码中关闭括号时,类似于 xcode 执行相同操作的方式进行动画处理 Is there any way of doing this?有没有办法做到这一点?

Any help is greatly appreciated, though I'm fairly new to this, so please don't assume I know too much :)非常感谢任何帮助,尽管我对此很陌生,所以请不要假设我知道太多:)

Here's my code:这是我的代码:

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

As you can see I've tried using the UIView.animateWithDuration to do this, which as I suspected, didn't work.正如您所看到的,我已经尝试使用 UIView.animateWithDuration 来执行此操作,正如我所怀疑的那样,这不起作用。

Another solution which works for me (Swift 4) is to generate multiple attributed strings, assign one to label and then replace the content ( attributedText ) inside transition animation block.另一个对我有用的解决方案(Swift 4)是生成多个属性字符串,将一个分配给标签,然后替换过渡动画块内的内容( attributedText文本)。 For example:例如:

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

} }

Don't forget to use .transitionCrossDissolve in the animation options.不要忘记在动画选项中使用.transitionCrossDissolve

I achieved what I wanted to by getting the frames for the actual parentheses and creating new UILabels on top of my UITextView and animating those labels.我通过获取实际括号的框架并在我的 UITextView 顶部创建新的 UILabels 并为这些标签设置动画来实现我想要的。

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

}

There's a much easier way to do this, which you can see in this answer: Animate text change in UILabel .有一种更简单的方法可以做到这一点,您可以在此答案中看到: 在 UILabel 中动画文本更改

You just have to set the label.attributedText property instead:你只需要设置label.attributedText属性:

UIView.transition(
    with: label,
    duration: 0.15,
    options: .transitionCrossDissolve,
    animations: {
        label.attributedText = NSAttributedString(string: text, attributes: attributes)
    },
    completion: nil
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 更改 NSMutableAttributedString 中链接的颜色 - Change the color of a link in an NSMutableAttributedString NSMutableAttributedString无法正常工作:将NSString的部分加粗 - NSMutableAttributedString not working: bold the part of NSString 更改NSMutableAttributedString中单个字符的颜色 - change color for single character in NSMutableAttributedString 无法更改NSMutableAttributedString的颜色 - Can't change color of NSMutableAttributedString 更改NSMutableAttributedString的多个部分的属性 - Change attributes of multiple parts of a NSMutableAttributedString 在 iOS 8 中使用 NSMutableAttributedString 的字符串的下划线部分不起作用 - Underline part of a string using NSMutableAttributedString in iOS 8 is not working 使用NSMutableAttributedString在Swift中的UITextView中的粗体文本 - Bold part of the text in UITextView in Swift using NSMutableAttributedString 如何更改NSMutableAttributedString的默认字体和字体大小 - how to change the default font and font size of NSMutableAttributedString 使用NSMutableAttributedString更改NSString的颜色和大小部分 - Change color and size portion of NSString with NSMutableAttributedString 使用NSMutableAttributedString更改UITextView中小词的颜色(“ in”) - Change Colour of Small Words ('in') in UITextView using NSMutableAttributedString
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM