Skip to content

Instantly share code, notes, and snippets.

@defagos
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save defagos/ea9a05cc751943337d56 to your computer and use it in GitHub Desktop.
Save defagos/ea9a05cc751943337d56 to your computer and use it in GitHub Desktop.
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
//
// 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