A category for iOS 7 ensuring that UITextView cursor stays within the content area defined by its contentInset. This behavior is standard in iOS 8
This file contains 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 characters
// | |
// UITextView+SDECursorVisibility.m | |
// | |
// Created by Samuel Défago on 29.10.14. | |
// | |
#import <UIKit/UIKit.h> | |
@interface UITextView (SDECursorVisibility) | |
+ (void)sde_enableCursorVisibility; | |
@end | |
static __attribute__ ((constructor)) void SDEEnableUITextViewCursorVisibilityConstructor(void) | |
{ | |
[UITextView sde_enableCursorVisibility]; | |
} | |
@implementation UITextView (CursorVisibility) | |
+ (void)sde_enableCursorVisibility | |
{ | |
// Not needed on iOS 8 | |
if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) { | |
return; | |
} | |
[[NSNotificationCenter defaultCenter] addObserver:self | |
selector:@selector(sde_textViewDidChangeCursorPosition:) | |
name:UITextViewTextDidBeginEditingNotification | |
object:nil]; | |
[[NSNotificationCenter defaultCenter] addObserver:self | |
selector:@selector(sde_textViewDidChangeCursorPosition:) | |
name:UITextViewTextDidChangeNotification | |
object:nil]; | |
} | |
+ (void)sde_textViewDidChangeCursorPosition:(NSNotification *)notification | |
{ | |
NSAssert([notification.object isKindOfClass:[UITextView class]], @"Expect a text view"); | |
// Wait a little bit to have the most recent cursor position | |
[notification.object performSelector:@selector(sde_scrollCursorToVisible) withObject:nil afterDelay:0.05]; | |
} | |
- (void)sde_scrollCursorToVisible | |
{ | |
UIView *cursorView = self; | |
while ([cursorView.subviews count] != 0) { | |
cursorView = [cursorView.subviews firstObject]; | |
} | |
static const CGFloat kCursorVisibilityMargin = 10.f; | |
CGRect cursorViewFrameInTextView = [self convertRect:cursorView.bounds fromView:cursorView]; | |
CGRect enlargedCursorViewFrameInTextView = CGRectMake(CGRectGetMinX(cursorViewFrameInTextView) - kCursorVisibilityMargin, | |
CGRectGetMinY(cursorViewFrameInTextView) - kCursorVisibilityMargin, | |
CGRectGetWidth(cursorViewFrameInTextView) + 2 * kCursorVisibilityMargin, | |
CGRectGetHeight(cursorViewFrameInTextView) + 2 * kCursorVisibilityMargin); | |
[UIView animateWithDuration:0.25 animations:^{ | |
[self scrollRectToVisible:enlargedCursorViewFrameInTextView animated:NO]; | |
}]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment