Created
August 15, 2017 05:39
-
-
Save jellybeansoup/d24cc0f2d7240f46f5e91bf25d397c08 to your computer and use it in GitHub Desktop.
Revisions
-
jellybeansoup created this gist
Aug 15, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,77 @@ // Exists inside of a scrollview subclass containing an "expanding" textview that lives underneath other content. private var previousSelection: CGRect? func textViewDidChangeSelection(_ textView: UITextView) { guard textView.isFirstResponder else { return } var selection = textView.layoutManager.boundingRect(forGlyphRange: textView.selectedRange, in: textView.textContainer).offsetBy(dx: insets.left, dy: insets.top) let contentInset: UIEdgeInsets if #available(iOS 11.0, *) { contentInset = self.adjustedContentInset } else { contentInset = self.contentInset } let scale = UIScreen.main.scale let selectionOrigin = round(selection.origin.y / scale) * scale let selectionHeight = round(selection.size.height / scale) * scale let absoluteMinY = 0 - contentInset.top let absoluteMaxY = self.contentSize.height - self.bounds.height + contentInset.bottom let selectionMinY = selectionOrigin - textView.textContainerInset.top + (textView.frame.origin.y - contentInset.top) let selectionMaxY = (textView.frame.origin.y + selectionOrigin + selectionHeight + textView.textContainerInset.bottom) - (self.bounds.height - contentInset.bottom) if let previous = previousSelection { let expanding = selection.height > previous.height let contracting = selection.height < previous.height let moving = !expanding && !contracting let offsetY: CGFloat if expanding, selection.minY < previous.minY { offsetY = selectionMinY // up } else if expanding, selection.maxY > previous.maxY { offsetY = selectionMaxY // down } else if contracting, selection.minY > previous.minY { offsetY = selectionMinY // up } else if contracting, selection.maxY < previous.maxY { offsetY = selectionMaxY // down } else if moving, selection.minY < previous.minY { offsetY = selectionMinY // up } else if moving, selection.maxY > previous.maxY { offsetY = selectionMaxY // down } else { return } if offsetY == selectionMinY, offsetY < self.contentOffset.y { self.contentOffset = CGPoint(x: self.contentOffset.x, y: min(max(offsetY, absoluteMinY), absoluteMaxY)) } else if offsetY == selectionMaxY, offsetY > self.contentOffset.y { self.contentOffset = CGPoint(x: self.contentOffset.x, y: min(max(offsetY, absoluteMinY), absoluteMaxY)) } else if selectionMinY < self.contentOffset.y { self.contentOffset = CGPoint(x: self.contentOffset.x, y: min(max(selectionMinY, absoluteMinY), absoluteMaxY)) } else if selectionMaxY > self.contentOffset.y { self.contentOffset = CGPoint(x: self.contentOffset.x, y: min(max(selectionMaxY, absoluteMinY), absoluteMaxY)) } } else if selectionMinY < self.contentOffset.y { self.contentOffset = CGPoint(x: self.contentOffset.x, y: min(max(selectionMinY, absoluteMinY), absoluteMaxY)) } else if selectionMaxY > self.contentOffset.y { self.contentOffset = CGPoint(x: self.contentOffset.x, y: min(max(selectionMaxY, absoluteMinY), absoluteMaxY)) } self.previousSelection = selection }