Search code examples
iosanimationswift3textviewlines

Apply animation duration depending on number of lines in textview (swif3)


My code here animates the textview and scrolls it down.

        UIView.animate(withDuration: 10) { // 10 seconds
        self.textView.contentOffset = CGPoint(x: 0, y: 225)
    }

The problem is that it follows the same command now matter how many lines are in the textfield. What I would like to do is have the animation follow a line ratio that determines how long the duration goes for. For example for every 3 lines in the textfield it adds 1 second in duration. So if there are a total of 21 lines in the textview the duration length is going to be 7 seconds long.


Solution

  • Try this

        // Calculate number of lines according to font
        var font = UIFont.boldSystemFont(ofSize: CGFloat(11.0))
        var size: CGSize = string.size(with: font, constrainedToSize: textView.frame.size, lineBreakMode: .wordWrap) // default mode
        var numberOfLines: Float = size.height / font.lineHeight
    
        // 1 sec per third line
        let duration = Int(numberOfLines / 3)
    
        UIView.animate(withDuration: TimeInterval(duration)) {
            self.textView.contentOffset = CGPoint(x: 0, y: 225)
        }
    

    Or you could use an extension

    extension UITextView {
        func numberOfLines() -> Int {
            let layoutManager = self.layoutManager
            let numberOfGlyphs = layoutManager.numberOfGlyphs
            var lineRange: NSRange = NSMakeRange(0, 1)
            var index = 0
            var numberOfLines = 0
    
            while index < numberOfGlyphs {
                layoutManager.lineFragmentRectForGlyphAtIndex(
                    index, effectiveRange: &lineRange
                )
                index = NSMaxRange(lineRange)
                numberOfLines += 1
            }
            return numberOfLines
        }
    }
    

    and then calculate the duration

       // 1 sec per third line
       let duration = Int(textView.numberOfLines() / 3)
    
    
       UIView.animate(withDuration: TimeInterval(duration)) {            
             self.textView.contentOffset = CGPoint(x: 0, y: 225)
        }