FLEXArgumentInputTextView.m 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //
  2. // FLEXArgumentInputTextView.m
  3. // FLEXInjected
  4. //
  5. // Created by Ryan Olson on 6/15/14.
  6. //
  7. //
  8. #import "FLEXColor.h"
  9. #import "FLEXArgumentInputTextView.h"
  10. #import "FLEXUtility.h"
  11. @interface FLEXArgumentInputTextView ()
  12. #if TARGET_OS_TV
  13. @property (nonatomic) KBSelectableTextView *inputTextView;
  14. #else
  15. @property (nonatomic) UITextView *inputTextView;
  16. #endif
  17. @property (nonatomic) UILabel *placeholderLabel;
  18. @property (nonatomic, readonly) NSUInteger numberOfInputLines;
  19. @end
  20. @implementation FLEXArgumentInputTextView
  21. - (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding {
  22. self = [super initWithArgumentTypeEncoding:typeEncoding];
  23. if (self) {
  24. #if TARGET_OS_TV
  25. self.inputTextView = [[KBSelectableTextView alloc] initWithFrame:CGRectZero];
  26. #else
  27. self.inputTextView = [UITextView new];
  28. #endif
  29. self.inputTextView.font = [[self class] inputFont];
  30. self.inputTextView.backgroundColor = FLEXColor.secondaryGroupedBackgroundColor;
  31. self.inputTextView.layer.cornerRadius = 10.f;
  32. self.inputTextView.contentInset = UIEdgeInsetsMake(0, 5, 0, 0);
  33. self.inputTextView.autocapitalizationType = UITextAutocapitalizationTypeNone;
  34. self.inputTextView.autocorrectionType = UITextAutocorrectionTypeNo;
  35. self.inputTextView.delegate = self;
  36. #if !TARGET_OS_TV
  37. self.inputTextView.inputAccessoryView = [self createToolBar];
  38. #endif
  39. if (@available(iOS 11, *)) {
  40. [self.inputTextView.layer setValue:@YES forKey:@"continuousCorners"];
  41. } else {
  42. self.inputTextView.layer.borderWidth = 1.f;
  43. self.inputTextView.layer.borderColor = FLEXColor.borderColor.CGColor;
  44. }
  45. self.placeholderLabel = [UILabel new];
  46. self.placeholderLabel.font = self.inputTextView.font;
  47. self.placeholderLabel.textColor = FLEXColor.deemphasizedTextColor;
  48. self.placeholderLabel.numberOfLines = 0;
  49. [self addSubview:self.inputTextView];
  50. [self.inputTextView addSubview:self.placeholderLabel];
  51. }
  52. return self;
  53. }
  54. #pragma mark - Private
  55. #if !TARGET_OS_TV
  56. - (UIToolbar *)createToolBar {
  57. UIToolbar *toolBar = [UIToolbar new];
  58. [toolBar sizeToFit];
  59. UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc]
  60. initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
  61. target:nil action:nil
  62. ];
  63. UIBarButtonItem *pasteItem = [[UIBarButtonItem alloc]
  64. initWithTitle:@"Paste" style:UIBarButtonItemStyleDone
  65. target:self.inputTextView action:@selector(paste:)
  66. ];
  67. UIBarButtonItem *doneItem = [[UIBarButtonItem alloc]
  68. initWithBarButtonSystemItem:UIBarButtonSystemItemDone
  69. target:self.inputTextView action:@selector(resignFirstResponder)
  70. ];
  71. toolBar.items = @[spaceItem, pasteItem, doneItem];
  72. return toolBar;
  73. }
  74. #endif
  75. - (void)setInputPlaceholderText:(NSString *)placeholder {
  76. self.placeholderLabel.text = placeholder;
  77. if (placeholder.length) {
  78. if (!self.inputTextView.text.length) {
  79. self.placeholderLabel.hidden = NO;
  80. } else {
  81. self.placeholderLabel.hidden = YES;
  82. }
  83. } else {
  84. self.placeholderLabel.hidden = YES;
  85. }
  86. [self setNeedsLayout];
  87. }
  88. - (NSString *)inputPlaceholderText {
  89. return self.placeholderLabel.text;
  90. }
  91. #pragma mark - Superclass Overrides
  92. - (BOOL)inputViewIsFirstResponder {
  93. return self.inputTextView.isFirstResponder;
  94. }
  95. #pragma mark - Layout and Sizing
  96. - (void)layoutSubviews {
  97. [super layoutSubviews];
  98. self.inputTextView.frame = CGRectMake(0, self.topInputFieldVerticalLayoutGuide, self.bounds.size.width, [self inputTextViewHeight]);
  99. // Placeholder label is positioned by insetting then origin
  100. // by the content inset then the text container inset
  101. CGSize s = self.inputTextView.frame.size;
  102. self.placeholderLabel.frame = CGRectMake(0, 0, s.width, s.height);
  103. self.placeholderLabel.frame = UIEdgeInsetsInsetRect(
  104. UIEdgeInsetsInsetRect(self.placeholderLabel.frame, self.inputTextView.contentInset),
  105. self.inputTextView.textContainerInset
  106. );
  107. }
  108. - (NSUInteger)numberOfInputLines {
  109. switch (self.targetSize) {
  110. case FLEXArgumentInputViewSizeDefault:
  111. return 2;
  112. case FLEXArgumentInputViewSizeSmall:
  113. return 1;
  114. case FLEXArgumentInputViewSizeLarge:
  115. return 8;
  116. }
  117. }
  118. - (CGFloat)inputTextViewHeight {
  119. CGFloat padding = 16.0;
  120. #if TARGET_OS_TV
  121. padding = 40.0;
  122. #endif
  123. return ceil([[self class] inputFont].lineHeight * self.numberOfInputLines) + padding;
  124. }
  125. - (CGSize)sizeThatFits:(CGSize)size {
  126. CGSize fitSize = [super sizeThatFits:size];
  127. fitSize.height += [self inputTextViewHeight];
  128. return fitSize;
  129. }
  130. #pragma mark - Class Helpers
  131. + (UIFont *)inputFont {
  132. return [UIFont systemFontOfSize:14.0];
  133. }
  134. #pragma mark - UITextViewDelegate
  135. - (void)textViewDidChange:(UITextView *)textView {
  136. [self.delegate argumentInputViewValueDidChange:self];
  137. self.placeholderLabel.hidden = !(self.inputPlaceholderText.length && !textView.text.length);
  138. }
  139. @end