IQTextView.m 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. //
  2. // IQTextView.m
  3. // https://github.com/hackiftekhar/IQKeyboardManager
  4. // Copyright (c) 2013-16 Iftekhar Qurashi.
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. #import "IQTextView.h"
  24. #import <UIKit/NSTextContainer.h>
  25. #import <UIKit/UILabel.h>
  26. #import <UIKit/UINibLoading.h>
  27. @interface IQTextView ()
  28. @property(nonatomic, strong) UILabel *placeholderLabel;
  29. @end
  30. @implementation IQTextView
  31. @synthesize placeholder = _placeholder;
  32. @synthesize placeholderLabel = _placeholderLabel;
  33. @synthesize placeholderTextColor = _placeholderTextColor;
  34. -(void)initialize
  35. {
  36. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshPlaceholder) name:UITextViewTextDidChangeNotification object:self];
  37. }
  38. -(void)dealloc
  39. {
  40. [_placeholderLabel removeFromSuperview];
  41. _placeholderLabel = nil;
  42. [[NSNotificationCenter defaultCenter] removeObserver:self];
  43. }
  44. - (instancetype)init
  45. {
  46. self = [super init];
  47. if (self) {
  48. [self initialize];
  49. }
  50. return self;
  51. }
  52. -(void)awakeFromNib
  53. {
  54. [super awakeFromNib];
  55. [self initialize];
  56. }
  57. -(void)refreshPlaceholder
  58. {
  59. if([[self text] length] || [[self attributedText] length])
  60. {
  61. [_placeholderLabel setAlpha:0];
  62. }
  63. else
  64. {
  65. [_placeholderLabel setAlpha:1];
  66. }
  67. [self setNeedsLayout];
  68. [self layoutIfNeeded];
  69. }
  70. - (void)setText:(NSString *)text
  71. {
  72. [super setText:text];
  73. [self refreshPlaceholder];
  74. }
  75. -(void)setAttributedText:(NSAttributedString *)attributedText
  76. {
  77. [super setAttributedText:attributedText];
  78. [self refreshPlaceholder];
  79. }
  80. -(void)setFont:(UIFont *)font
  81. {
  82. [super setFont:font];
  83. self.placeholderLabel.font = self.font;
  84. [self setNeedsLayout];
  85. [self layoutIfNeeded];
  86. }
  87. -(void)setTextAlignment:(NSTextAlignment)textAlignment
  88. {
  89. [super setTextAlignment:textAlignment];
  90. self.placeholderLabel.textAlignment = textAlignment;
  91. [self setNeedsLayout];
  92. [self layoutIfNeeded];
  93. }
  94. -(void)layoutSubviews
  95. {
  96. [super layoutSubviews];
  97. self.placeholderLabel.frame = [self placeholderExpectedFrame];
  98. }
  99. -(void)setPlaceholder:(NSString *)placeholder
  100. {
  101. _placeholder = placeholder;
  102. self.placeholderLabel.text = placeholder;
  103. [self refreshPlaceholder];
  104. }
  105. -(void)setAttributedPlaceholder:(NSAttributedString *)attributedPlaceholder
  106. {
  107. _attributedPlaceholder = attributedPlaceholder;
  108. self.placeholderLabel.attributedText = attributedPlaceholder;
  109. [self refreshPlaceholder];
  110. }
  111. -(void)setPlaceholderTextColor:(UIColor*)placeholderTextColor
  112. {
  113. _placeholderTextColor = placeholderTextColor;
  114. self.placeholderLabel.textColor = placeholderTextColor;
  115. }
  116. -(UIEdgeInsets)placeholderInsets
  117. {
  118. return UIEdgeInsetsMake(self.textContainerInset.top, self.textContainerInset.left + self.textContainer.lineFragmentPadding, self.textContainerInset.bottom, self.textContainerInset.right + self.textContainer.lineFragmentPadding);
  119. }
  120. -(CGRect)placeholderExpectedFrame
  121. {
  122. UIEdgeInsets placeholderInsets = [self placeholderInsets];
  123. CGFloat maxWidth = CGRectGetWidth(self.frame)-placeholderInsets.left-placeholderInsets.right;
  124. CGSize expectedSize = [self.placeholderLabel sizeThatFits:CGSizeMake(maxWidth, CGRectGetHeight(self.frame)-placeholderInsets.top-placeholderInsets.bottom)];
  125. return CGRectMake(placeholderInsets.left, placeholderInsets.top, maxWidth, expectedSize.height);
  126. }
  127. -(UILabel*)placeholderLabel
  128. {
  129. if (_placeholderLabel == nil)
  130. {
  131. _placeholderLabel = [[UILabel alloc] init];
  132. _placeholderLabel.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight);
  133. _placeholderLabel.lineBreakMode = NSLineBreakByWordWrapping;
  134. _placeholderLabel.numberOfLines = 0;
  135. _placeholderLabel.font = self.font;
  136. _placeholderLabel.textAlignment = self.textAlignment;
  137. _placeholderLabel.backgroundColor = [UIColor clearColor];
  138. _placeholderLabel.textColor = [UIColor colorWithWhite:0.7 alpha:1.0];
  139. _placeholderLabel.alpha = 0;
  140. [self addSubview:_placeholderLabel];
  141. }
  142. return _placeholderLabel;
  143. }
  144. //When any text changes on textField, the delegate getter is called. At this time we refresh the textView's placeholder
  145. -(id<UITextViewDelegate>)delegate
  146. {
  147. [self refreshPlaceholder];
  148. return [super delegate];
  149. }
  150. -(CGSize)intrinsicContentSize
  151. {
  152. if (self.hasText) {
  153. return [super intrinsicContentSize];
  154. }
  155. UIEdgeInsets placeholderInsets = [self placeholderInsets];
  156. CGSize newSize = [super intrinsicContentSize];
  157. newSize.height = [self placeholderExpectedFrame].size.height + placeholderInsets.top + placeholderInsets.bottom;
  158. return newSize;
  159. }
  160. @end