Created
March 17, 2014 10:47
-
-
Save keicoder/9597222 to your computer and use it in GitHub Desktop.
objective-c : making UITextView programmatically with custom class and UITextViewDelegate (JTextView)
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 characters
//making UITextView programmatically with custom class and UITextViewDelegate (JTextView) | |
//1. make basic UITextView programmatically with custom class | |
//Prefix header | |
#ifdef __OBJC__ | |
#define debug 1 | |
#define kSTATUSBAR_OFFSET 20.0 // 스테이터스 바 높이 | |
#define kINSET_TOP 10.0 // 텍스트 뷰 인셋 top | |
#define kINSET_LEFT 10.0 // 텍스트 뷰 인셋 left | |
#define kINSET_BOTTOM 10.0 // 텍스트 뷰 인셋 bottom | |
#define kINSET_RIGHT 10.0 // 텍스트 뷰 인셋 right | |
#endif | |
//JTextView.h | |
@interface JTextView : UITextView | |
- (void)updateNoteTextViewFrame; | |
- (void)keyboardDidShow:(NSNotification *)notification; | |
- (void)keyboardWillHide:(NSNotification*)notification; | |
@end | |
//JTextView.m | |
@implementation JTextView | |
{ | |
CGRect _applicationFrame; | |
CGSize _keyboardSize; //width, height | |
} | |
#pragma mark - Class methods | |
//in case making JTextView in code | |
- (id)initWithFrame:(CGRect)frame | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
self = [super initWithFrame:frame]; | |
if (self) | |
{ | |
} | |
return self; | |
} | |
+ (void)initialize | |
{ | |
if (self == [JTextView class]) | |
[self conformsToProtocol:@protocol(UITextInput)]; | |
} | |
// Called when the UIKeyboardDidShowNotification is sent. | |
- (void)keyboardDidShow:(NSNotification *)notification | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
//키보드 사이즈 인스턴스 변수에 저장 | |
NSDictionary *userInfo = [notification userInfo]; | |
_keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; | |
// NSLog(@"_keyboardSize: %f, %f", _keyboardSize.width, _keyboardSize.height); | |
// CGPoint _keyboardOrigin = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].origin; | |
// NSLog(@"_keyboardOrigin: %f, %f", _keyboardOrigin.x, _keyboardOrigin.y); | |
// [self updateNoteTextViewFrame]; | |
[self updateNoteTextViewInset]; | |
} | |
// Called when the UIKeyboardWillHideNotification is sent | |
- (void)keyboardWillHide:(NSNotification*)notification | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
// [self updateNoteTextViewFrameInCaseDown]; | |
[self updateNoteTextViewInsetInCaseDown]; | |
} | |
//텍스트 뷰의 인셋 사이즈 변경 | |
- (void)updateNoteTextViewInset | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
// Step 1: Adjust the bottom content inset of your scroll view by the keyboard height. | |
UIEdgeInsets contentInset = self.contentInset; | |
contentInset.bottom = _keyboardSize.height; | |
self.contentInset = contentInset; | |
} | |
- (void)updateNoteTextViewInsetInCaseDown | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
UIEdgeInsets contentInsets = UIEdgeInsetsZero; | |
self.contentInset = contentInsets; | |
self.scrollIndicatorInsets = contentInsets; | |
} | |
//텍스트 뷰의 프레임 사이즈 변경 | |
- (void)updateNoteTextViewFrame | |
{ | |
self.frame = CGRectMake(0, kSTATUSBAR_OFFSET, _applicationFrame.size.width, _applicationFrame.size.height - _keyboardSize.height); //kSTATUSBAR_OFFSET: 20 | |
} | |
- (void)updateNoteTextViewFrameInCaseDown | |
{ | |
_keyboardSize = CGSizeMake(0.0, 0.0); | |
[UIView animateWithDuration:0.3 animations:^{ | |
[self updateNoteTextViewFrame]; | |
}]; | |
} | |
@end | |
//AppDelegate.h | |
@interface AppDelegate : UIResponder <UIApplicationDelegate> | |
@property (strong, nonatomic) UIWindow *window; | |
@end | |
//AppDelegate.m | |
@implementation AppDelegate | |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | |
{ | |
return YES; | |
} | |
@end | |
//NoteViewController.h | |
@interface NoteViewController : UIViewController | |
@end | |
//NoteViewController.m | |
#import "JTextView.h" | |
@interface NoteViewController () <UITextViewDelegate> | |
@end | |
@implementation NoteViewController | |
{ | |
JTextView *_textView; | |
CGRect _applicationFrame; | |
} | |
- (void)loadView | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
_applicationFrame = [[UIScreen mainScreen] applicationFrame]; //Frame: : 0, 20, 320, 548 | |
//텍스트 뷰 생성 | |
_textView = [[JTextView alloc] initWithFrame:CGRectMake(0.0, kSTATUSBAR_OFFSET, _applicationFrame.size.width, _applicationFrame.size.height)]; //Frame: 0, 20, 320, 548, kSTATUSBAR_OFFSET: 20 | |
// CGRect textViewFrame = _textView.frame; | |
// NSLog (@"textViewFrame: %f, %f, %f, %f", textViewFrame.origin.x, textViewFrame.origin.y, textViewFrame.size.width, textViewFrame.size.height); | |
//텍스트 뷰 속성 | |
_textView.font = [UIFont systemFontOfSize:14]; //텍스트 뷰 폰트 | |
_textView.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.93 alpha:1]; | |
_textView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; | |
[_textView setTextContainerInset:UIEdgeInsetsMake(kINSET_TOP, kINSET_LEFT, kINSET_BOTTOM, kINSET_RIGHT)]; //텍스트 뷰 인셋 iOS 7 | |
CALayer *imageLayer = _textView.layer; | |
[imageLayer setCornerRadius:10]; | |
_textView.delegate = self; | |
//컨테이너 뷰 생성 | |
UIView *containerView = [[UIView alloc] initWithFrame:_applicationFrame]; | |
[containerView addSubview:_textView]; | |
//뷰 속성 | |
self.view = containerView; | |
self.view.backgroundColor = [UIColor colorWithRed:0.99 green:0.4 blue:0.43 alpha:1]; | |
} | |
#pragma mark - View Life Cycle | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
//더미 텍스트 파일 불러오기 | |
NSError *error; | |
NSString* path = [[NSBundle mainBundle] pathForResource:@"dummyText" ofType:@"txt"]; | |
NSString* content = [NSString stringWithContentsOfFile:path | |
encoding:NSUTF8StringEncoding | |
error:&error]; | |
_textView.text = content; | |
[self registerForKeyboardNotifications]; | |
} | |
- (void)viewWillDisappear:(BOOL)animated | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
[super viewWillDisappear:animated]; | |
[[NSNotificationCenter defaultCenter] removeObserver:self]; //키보드 옵저버 해제 | |
} | |
#pragma mark - Keyboard Notifications | |
// Call this method somewhere in your view controller setup code. | |
- (void)registerForKeyboardNotifications | |
{ | |
//키보드 팝업 옵저버 (키보드 팝업 시 텍스트 뷰 사이즈 조절) | |
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) | |
name:UIKeyboardDidShowNotification object:self.view.window]; | |
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) | |
name:UIKeyboardWillHideNotification object:self.view.window]; | |
} | |
// Called when the UIKeyboardDidShowNotification is sent. | |
- (void)keyboardDidShow:(NSNotification *)notification | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
[_textView keyboardDidShow:notification]; | |
[self moveTextToCaretPosition:_textView withAnimation:YES]; | |
} | |
// Called when the UIKeyboardWillHideNotification is sent | |
- (void)keyboardWillHide:(NSNotification*)notification | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
[_textView keyboardWillHide:notification]; | |
} | |
#pragma mark - UITextView delegate method (optional) | |
- (void)textViewDidBeginEditing:(UITextView *)textView | |
{ | |
_textView.backgroundColor = [UIColor colorWithRed:0.68 green:0.85 blue:0.94 alpha:1]; | |
} | |
- (void)textViewDidEndEditing:(UITextView *)textView | |
{ | |
_textView.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.93 alpha:1]; | |
} | |
#pragma mark UITextView change selection, text | |
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text | |
{ | |
return YES; | |
} | |
- (void)textViewDidChangeSelection:(UITextView *)textView | |
{ | |
} | |
- (void)textViewDidChange:(UITextView *)textView | |
{ | |
// if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
[self moveTextToCaretPosition:textView withAnimation:YES]; | |
} | |
- (void)moveTextToCaretPosition:(UITextView *)textView withAnimation:(BOOL)shouldAnimate | |
{ | |
// where the blinky caret is | |
CGRect caretRect = [textView caretRectForPosition:textView.selectedTextRange.start]; | |
CGFloat offscreen = caretRect.origin.y + caretRect.size.height - (textView.contentOffset.y + textView.bounds.size.height - textView.contentInset.bottom - textView.contentInset.top); | |
CGPoint offsetP = textView.contentOffset; | |
offsetP.y += offscreen + 1; // 3 px -- margin puts caret 3 px above bottom | |
if (offsetP.y >= 0) { | |
if (shouldAnimate) { | |
[UIView animateWithDuration:0.3 animations:^{ | |
[textView setContentOffset:offsetP]; | |
}]; | |
} | |
else { | |
[textView setContentOffset:offsetP]; | |
} | |
} | |
} | |
#pragma mark - Memory Warning | |
- (void)didReceiveMemoryWarning | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
[super didReceiveMemoryWarning]; | |
} | |
@end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment