CustomTextView.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. //
  2. // CustomTextView.m
  3. // JasonDevelop
  4. //
  5. // Created by Jason Lee on 10/26/14.
  6. // Copyright (c) jasondevelop. All rights reserved.
  7. //
  8. #import "NSString-Addtions.h"
  9. #import "CommonUtil.h"
  10. #import "CustomTextView.h"
  11. #import "ImageUtil.h"
  12. #define kUIBtnTintColor [UIColor whiteColor]
  13. #define kfBoxCap 4.0f
  14. #define kUIPlaceHolderColor RGBCOLOR(170, 170, 170)
  15. @interface CustomTextView () {
  16. @protected
  17. UIView *_targetSuperView;
  18. CGRect _cRect;
  19. CGRect _superRect;
  20. CGPoint _contentOffset;
  21. CGFloat _marginTop, _naviMargin, _adjustY;
  22. UIBarButtonItem *_btnPrev, *_btnNext, *_btnClose;
  23. UIToolbar *_toolBar;
  24. NSMutableArray *_barItems;
  25. UIBarButtonItem *_btnFlexibleSpace;
  26. UIEdgeInsets _bgInsets;
  27. BOOL _isSecureEntry;
  28. UIImage *_bgImage;
  29. BOOL _isScrollUp;
  30. UIColor *_normalTextColor;
  31. }
  32. @end
  33. @implementation CustomTextView
  34. @dynamic delegate;
  35. - (id)initWithFrame:(CGRect)frame {
  36. if (self = [super initWithFrame:frame]) {
  37. _customTextViewSuperview = CustomTextViewSuperviewIsViewController;
  38. self.inputAccessoryView = [self generateAccessoryView];
  39. _bgImageName = @"";
  40. UIImage *bgImage = [UIImage imageNamed:_bgImageName];
  41. if (bgImage) {
  42. _bgInsets = UIEdgeInsetsMake(kfBoxCap, kfBoxCap, kfBoxCap, kfBoxCap);
  43. bgImage = [ImageUtil resizableImageWithCapInsets:_bgInsets resizingMode:UIImageResizingModeStretch img:bgImage];
  44. // [self setBackground:bgImage];
  45. }
  46. _cRect = self.frame;
  47. }
  48. return self;
  49. }
  50. - (void)awakeFromNib {
  51. self.customTextViewSuperview = CustomTextViewSuperviewIsViewController;
  52. self.inputAccessoryView = [self generateAccessoryView];
  53. _bgImageName = _bgImageName && ![_bgImageName isEmptyString] ? _bgImageName : @"";
  54. _bgImage = [UIImage imageNamed:_bgImageName];
  55. if (_bgImage) {
  56. if (!CGRectEqualToRect(_rectForCapBackground, CGRectZero)) {//rectForCap이 설정된 경우, 이미지를 리사이즈함.
  57. CGFloat top, left, bottom, right;
  58. top = CGRectGetMinY(_rectForCapBackground);
  59. left = CGRectGetMinX(_rectForCapBackground);
  60. bottom = CGRectGetHeight(_rectForCapBackground);
  61. right = CGRectGetWidth(_rectForCapBackground);
  62. _bgInsets = UIEdgeInsetsMake(top, left, bottom, right);
  63. } else {
  64. _bgInsets = UIEdgeInsetsMake(kfBoxCap, kfBoxCap, kfBoxCap, kfBoxCap);
  65. }
  66. _bgImage = [ImageUtil resizableImageWithCapInsets:_bgInsets resizingMode:UIImageResizingModeStretch img:_bgImage];
  67. }
  68. _cRect = self.frame;
  69. _normalTextColor = self.textColor;
  70. if (_placeHolder) {
  71. self.text = _placeHolder;
  72. }
  73. #ifdef DEBUG
  74. NSString *identifier = [NSString stringWithFormat:@"%@", self.placeHolder];
  75. [self setValue:identifier forKey:@"layoutDebuggingIdentifier"];
  76. #endif
  77. self.textContainerInset = UIEdgeInsetsMake(12, 12, 12, 12);
  78. }
  79. - (void)drawRect:(CGRect)rect {
  80. _bgImage = [ImageUtil resizableImageWithCapInsets:_bgInsets resizingMode:UIImageResizingModeStretch img:_bgImage];
  81. [_bgImage drawInRect:rect];
  82. self.textColor = [self.text isEqualToString:_placeHolder] ? self.placeHolderColor : _normalTextColor;
  83. }
  84. - (UIView *)generateAccessoryView {
  85. CGFloat width = [UIScreen mainScreen].bounds.size.width;
  86. _toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, width, 44.0)];
  87. _toolBar.barStyle = UIBarStyleBlack;
  88. _toolBar.translucent = YES;
  89. _barItems = [NSMutableArray new];
  90. _btnFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
  91. _btnPrev = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"이전", @"이전")
  92. style:UIBarButtonItemStylePlain
  93. target:self
  94. action:@selector(goPrevField:)];
  95. _btnNext = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"다음", @"다음")
  96. style:UIBarButtonItemStylePlain
  97. target:self
  98. action:@selector(goNextField:)];
  99. _btnClose = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"닫기", @"닫기")
  100. style:UIBarButtonItemStylePlain
  101. target:self
  102. action:@selector(hideKeyboard:)];
  103. if (IOS_VERSION >= 7.0f) {
  104. _btnClose.tintColor = kUIBtnTintColor;
  105. _btnPrev.tintColor = kUIBtnTintColor;
  106. _btnNext.tintColor = kUIBtnTintColor;
  107. }
  108. [_barItems addObject:_btnFlexibleSpace];
  109. [_barItems addObject:_btnClose];
  110. [_toolBar setItems:_barItems animated:YES];
  111. return _toolBar;
  112. }
  113. - (void)setCustomTextViewMove:(CustomTextViewMove)customTextViewMove {
  114. [_barItems removeAllObjects];
  115. switch (customTextViewMove) {
  116. case CustomTextViewMovePrev:
  117. _btnNext.enabled = NO;
  118. [_barItems addObject:_btnPrev];
  119. [_barItems addObject:_btnNext];
  120. [_barItems addObject:_btnFlexibleSpace];
  121. [_barItems addObject:_btnClose];
  122. break;
  123. case CustomTextViewMoveNext:
  124. _btnPrev.enabled = NO;
  125. [_barItems addObject:_btnPrev];
  126. [_barItems addObject:_btnNext];
  127. [_barItems addObject:_btnFlexibleSpace];
  128. [_barItems addObject:_btnClose];
  129. break;
  130. case CustomTextVoewMoveBoth:
  131. [_barItems addObject:_btnPrev];
  132. [_barItems addObject:_btnNext];
  133. [_barItems addObject:_btnFlexibleSpace];
  134. [_barItems addObject:_btnClose];
  135. break;
  136. default:
  137. break;
  138. }
  139. [_toolBar setItems:_barItems animated:YES];
  140. }
  141. - (void)setCustomTextViewSuperview:(CustomTextViewSuperview)customTextViewSuperview {
  142. if (!_autoScrollUp) {
  143. return;
  144. }
  145. _customTextViewSuperview = customTextViewSuperview;
  146. _naviMargin = 20.0f;
  147. if (_customTextViewSuperview == CustomTextViewSuperviewIsViewController) {
  148. UIViewController *vc = [CommonUtil currentViewController];
  149. _targetSuperView = vc.view;
  150. } else if (_customTextViewSuperview == CustomTextViewSuperviewIsPopup) {
  151. _targetSuperView = self.superview.superview;
  152. } else if (_customTextViewSuperview == CustomTextViewSuperviewIsPopupContentView) {
  153. _targetSuperView = self.superview.superview.superview;
  154. } else if (_customTextViewSuperview == CustomTextViewSuperviewIsScrollView) {
  155. _targetSuperView = self.superview;
  156. if ([_targetSuperView isKindOfClass:[UIScrollView class]]) {
  157. UIScrollView *sv = (UIScrollView *)_targetSuperView;
  158. _contentOffset = sv.contentOffset;
  159. }
  160. }else if (_customTextViewSuperview == CustomTextViewSuperviewIsContentView) {
  161. _targetSuperView = self.superview.superview.superview;
  162. _naviMargin = 85.0f;
  163. }
  164. // if (_customTextViewSuperview == CustomTextViewSuperviewIsView) {
  165. // _targetSuperView = self.superview;
  166. // } else if (_customTextViewSuperview == CustomTextViewSuperviewIsViewController) {
  167. // UIViewController *vc = [AOTFacade facade].currentViewController;
  168. // _targetSuperView = vc.view;
  169. // } else if (_customTextViewSuperview == CustomTextViewSuperviewIsPopup) {
  170. // _targetSuperView = self.superview.superview;
  171. // }
  172. }
  173. - (void)scrollUp {
  174. if (_autoScrollUp) {
  175. if (CGRectEqualToRect(CGRectZero, gKeyboardRect)) {
  176. [self performSelector:@selector(scrollUp) withObject:nil afterDelay:0.1f];
  177. return;
  178. }
  179. if (!_targetSuperView) {
  180. [self setCustomTextViewSuperview:_customTextViewSuperview];
  181. }
  182. CGRect selfRect = self.frame;
  183. if (CGRectEqualToRect(_superRect, CGRectZero)) {//기존 위치를 저장함.
  184. _superRect = _targetSuperView.frame;
  185. }
  186. CGRect cr = [self.superview convertRect:selfRect toView:_targetSuperView];
  187. if (_customTextViewSuperview == CustomTextViewSuperviewIsPopupContentView || _customTextViewSuperview == CustomTextViewSuperviewIsChildViewController) {
  188. cr = [self.superview convertRect:selfRect toView:[[UIApplication sharedApplication].delegate window]];
  189. }
  190. CGFloat cy = CGRectGetMaxY(cr) + _adjustY;
  191. CGFloat ay = gKeyboardRect.size.height + 30;//(gKeyboardRect.size.height + KEYBOARD_ACCESSORY_HEIGHT + KEYBOARD_PREDICTS_HEIGHT);
  192. CGFloat ky = ([UIScreen mainScreen].bounds.size.height - _naviMargin) - ay; // 260
  193. if (cy >= ky) {
  194. __block CGRect scrollRect = _targetSuperView.frame;
  195. scrollRect.origin.y = ky - cy;
  196. [UIView animateWithDuration:kfAnimationDur animations:^{
  197. if ([_targetSuperView isKindOfClass:[UIScrollView class]]) {
  198. CGFloat offsetY = _contentOffset.y + (cy - ky);
  199. [(UIScrollView *)_targetSuperView setContentOffset:CGPointMake(0, offsetY) animated:NO];
  200. } else {
  201. if (_customTextViewSuperview == CustomTextViewSuperviewIsPopupContentView || _customTextViewSuperview == CustomTextViewSuperviewIsChildViewController) {
  202. scrollRect.origin.y += _superRect.origin.y;
  203. }
  204. _targetSuperView.frame = scrollRect;
  205. }
  206. } completion:^(BOOL finished) {
  207. _isScrollUp = YES;
  208. }];
  209. } else {
  210. if (!CGRectEqualToRect(_superRect, CGRectZero)) {
  211. [UIView animateWithDuration:kfAnimationDur animations:^{
  212. _targetSuperView.frame = _superRect;
  213. } completion:^(BOOL finished) {
  214. _isScrollUp = YES;
  215. }];
  216. }
  217. }
  218. }
  219. }
  220. - (BOOL)becomeFirstResponder {
  221. if ([_placeHolder isEqualToString:self.text]) {
  222. self.text = ksEmptyString;
  223. }
  224. //redraw background image
  225. _bgImage = _bgPressImageName && ![_bgPressImageName isEmptyString] ? [UIImage imageNamed:_bgPressImageName] : _bgImage;
  226. [self setNeedsDisplay];
  227. if (_isScrollUp) {
  228. return [super becomeFirstResponder];
  229. }
  230. _isScrollUp = NO;
  231. [self scrollUp];
  232. return [super becomeFirstResponder];
  233. }
  234. - (BOOL)resignFirstResponder {
  235. // NSLog(@"%@, resignFirstResponder", self);
  236. if ([self.text isEqualToString:ksEmptyString]) {
  237. self.text = _placeHolder;
  238. }
  239. //redraw background image
  240. _bgImage = _bgImageName && ![_bgImageName isEmptyString] ? [UIImage imageNamed:_bgImageName] : [UIImage imageNamed:@"input_wh"];
  241. [self setNeedsDisplay];
  242. if (_autoScrollUp) {
  243. // if (_customTextViewSuperview == CustomTextViewSuperviewIsViewController) {
  244. // UIViewController *vc = [CommonUtil currentViewController];
  245. // _targetSuperView = vc.view;
  246. // } else if (_customTextViewSuperview == CustomTextViewSuperviewIsPopup) {
  247. // _targetSuperView = self.superview.superview;
  248. // }
  249. [UIView animateWithDuration:kfAnimationDur animations:^{
  250. if ([_targetSuperView isKindOfClass:[UIScrollView class]]) {
  251. [(UIScrollView *)_targetSuperView setContentOffset:_contentOffset animated:NO];
  252. } else if (!CGRectIsEmpty(_superRect)) {
  253. _targetSuperView.frame = _superRect;
  254. NSLog(@"_superRect2 %@", NSStringFromCGRect(_superRect));
  255. }
  256. } completion:^(BOOL finished) {
  257. _isScrollUp = NO;
  258. }];
  259. }
  260. return [super resignFirstResponder];
  261. }
  262. - (void)goPrevField:(id)sender {
  263. [self resignFirstResponder];
  264. if ([self.delegate respondsToSelector:@selector(moveToPrevField:)]) {
  265. [self.delegate moveToPrevField:self];
  266. }
  267. }
  268. - (void)goNextField:(id)sender {
  269. [self resignFirstResponder];
  270. if ([self.delegate respondsToSelector:@selector(moveToNextField:)]) {
  271. [self.delegate moveToNextField:self];
  272. }
  273. }
  274. - (void)hideKeyboard:(id)sender {
  275. [self resignFirstResponder];
  276. if ([self.delegate respondsToSelector:@selector(willHideKeyboard:)]) {
  277. [self.delegate willHideKeyboard:self];
  278. }
  279. }
  280. //-(void)textViewDidChange:(UITextView *)textView {
  281. // // Enable and disable lblPlaceHolderText
  282. // if ([textView.text length] > 0) {
  283. // [textView setBackgroundColor:[UIColor whiteColor]];
  284. //// [lblPlaceHolderText setHidden:YES];
  285. // } else {
  286. // [textView setBackgroundColor:[UIColor clearColor]];
  287. //// [lblPlaceHolderText setHidden:NO];
  288. // }
  289. //}
  290. @end