当设置了 scrollEnabled 为 NO 以后,当输入的文字超出可显示区域以后,第一行的左上角会出现一个很小的闪烁的光标,虽然是系统的默认实现,但是看上去就像是个 bug
1
| textView.scrollEnabled = NO;
|
(此处省略截图)
解决思路
监听文字输入是否超出,超出以后隐藏光标,焦点在可视范围内的时候显示光标。
光标隐藏
光标创建逻辑被封装在 UITextView 内部,无法直接访问,不过我们可以通过修改 tintColor 来实现
UITextView+CaretUtil
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| @interface UITextView (CaretUtil) @property (nonatomic, strong) UIColor *originTextViewTintColor; - (void)updateCaretColor; @end
#import "UITextView+CaretUtil.h" #import <objc/runtime.h>
static void *kOriginTextViewTintColorKey = "OriginTextViewTintColor";
@implementation UITextView (CaretUtil)
- (void)updateCaretColor { if (self.selectedTextRange) { NSLayoutManager *layoutManager = self.layoutManager; NSTextContainer *textContainer = self.textContainer; UITextPosition *beginning = self.beginningOfDocument; UITextRange *selectedRange = self.selectedTextRange; UITextPosition *selectionStart = selectedRange.start; UITextPosition *selectionEnd = selectedRange.end; const NSInteger location = [self offsetFromPosition:beginning toPosition:selectionStart]; const NSInteger length = [self offsetFromPosition:selectionStart toPosition:selectionEnd]; NSRange textRange = NSMakeRange(location, length); NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:textRange actualCharacterRange:nil]; CGRect caretRect = [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer]; if (caretRect.size.height == 0) { self.tintColor = [UIColor clearColor]; } else { self.tintColor = self.originTextViewTintColor; } } }
- (void)setOriginTextViewTintColor:(UIColor *)originTextViewTintColor { objc_setAssociatedObject(self, kOriginTextViewTintColorKey, originTextViewTintColor, OBJC_ASSOCIATION_RETAIN); }
- (UIColor *)originTextViewTintColor { return objc_getAssociatedObject(self, kOriginTextViewTintColorKey); }
@end
|
选中的时候更新光标颜色
这里直接采取继承,覆写 setSelectedTextRange: 方法,希望代码侵入性低一点的可以选择 AOP
1 2 3 4
| - (void)setSelectedTextRange:(UITextRange *)selectedTextRange { [super setSelectedTextRange:selectedTextRange]; [self updateCaretColor]; }
|
###TextView Delegate 中更新光标颜色
1 2 3 4 5 6 7
| - (void)textViewDidChange:(UITextView *)textView { [textView updateCaretColor]; }
- (void)textViewDidBeginEditing:(UITextView *)textView { [textView updateCaretColor]; }
|