iOS UITextField禁止選中文字(How to disable the selection of a UITextField?)
主題列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, greenwillow, v-green, vue-pro, healer-readable, mk-cute, jzman, geek-black, awesome-green, qklhk-chocolate
貢獻主題:https://github.com/xitu/juejin-markdown-themes
theme: fancy highlight:
背景:
最近在做輸入框的需求, 要求:
- 不能顯示選中文字(圖中標註的2)
- 不能彈出氣泡(圖中標註的1)。
分析:
-
不能彈出氣泡(圖中標註的1)。 這個好做,也是搜尋結果中最多的,
canPerformAction
根據需要返回NO
即可。 -
不能彈出氣泡(圖中標註的1)。 這個就不常見中文搜尋不到,用英文搜尋How to disable the selection of a UITextField?,得到一個答案。 ```ObjC
-
(CGRect)caretRectForPosition:(UITextPosition*) position { return CGRectNull; }
-
(NSArray )selectionRectsForRange:(UITextRange )range { return nil; }
-
(BOOL)canPerformAction:(SEL)action withSender:(id)sender { return NO; } ```
用UITextField
的子類,重寫一下上面的方法,好傢伙游標都沒了。雖然沒有達到理想效果,感覺接近了。
我繼續找官方對幾個API
的註釋,找到一個關鍵的方法,大概就是選中文字的繪製矩形框UITextSelectionRect
,
ObjC
- (NSArray<UITextSelectionRect *> *)selectionRectsForRange:(UITextRange *)range API_AVAILABLE(ios(6.0)); // Returns an array of UITextSelectionRects
UITextSelectionRect
找到這個關鍵的類,就看下怎麼初始化一個新的rect
,返回自己想要的就可以了。
```ObjC
UIKIT_EXTERN API_AVAILABLE(ios(6.0)) NS_SWIFT_UI_ACTOR
@interface UITextSelectionRect : NSObject
@property (nonatomic, readonly) CGRect rect; @property (nonatomic, readonly) NSWritingDirection writingDirection; @property (nonatomic, readonly) BOOL containsStart; // Returns YES if the rect contains the start of the selection. @property (nonatomic, readonly) BOOL containsEnd; // Returns YES if the rect contains the end of the selection. @property (nonatomic, readonly) BOOL isVertical; // Returns YES if the rect is for vertically oriented text.
@end
``
這個類沒有初始化方法,就得繼承一個子類,實現屬性的
get方法就可以了。
從屬性的名稱可以看到,
rect`就是我們想要的。
1. 返回CGRectZero
ObjC
- (CGRect)rect{
return CGRectZero;
}
問題:
-
矩形框確實縮小了,但是在左上角了。
-
使用刪除鍵的時候,還是全部刪除了。 也就是說,我們改變了繪製的矩形,但是還是完全選中的。
2. 返回CGRectNull
objc
- (CGRect)rect{
return CGRectNull;
}
確實沒有矩形了,但是使用刪除鍵,還是會全部刪除。
最後我們只需要解決最後一個問題:如何取消選中?
如何取消選中?
如何知道當前是否被選中?
```objC
// UITextField的子類.m
- (NSArray
}
}
return arr;
}
``
經過嘗試發現
tmpRect.rect.size.width就可以得到選中的寬度,想要自定義選中寬度的就可以動態改變它。
那麼
tmpRect.rect.size.width > 0`就可以知道當前被選中了。
如何取消選中?
看到UITextRange
大概就能猜到,可以移動游標來取消選中,那就每次選中的時候,將游標移動到末尾。
ObjC
// UITextField的子類.m
// CSTextSelectionRect是UITextSelectionRect的子類
- (NSArray<UITextSelectionRect *> *)selectionRectsForRange:(UITextRange *)range {
NSArray *arr = [super selectionRectsForRange:range];
for (UITextSelectionRect *tmpRect in arr) {
if (tmpRect.rect.size.width > 0) {
UITextPosition *endPosition = [self endOfDocument];
UITextRange *textRange =[self textRangeFromPosition:endPosition
toPosition:endPosition];
[self setSelectedTextRange:textRange];
return @[CSTextSelectionRect.new];
}
}
return arr;
}
總結:
- 新建
UITextField
一個子類,重寫selectionRectsForRange
方法。(實現沒有選中的顯示效果) - 新建
UITextSelectionRect
一個子類,重寫rect
方法,返回CGRectNull
。(實現沒有選中的顯示效果) - 選中的時候,移動游標在末尾。(實現真正沒有選中)