TL; DR: 您可以使用-(NSArray *)selectionRectsForRange
,這種行爲很古怪,但沒有很好地記錄。調用-(NSArray *)selectionRectsForRange
時由UITextView
返回的最後兩個矩形的寬度爲零,它們確定開始和結束遊標的高度。創建一個子類,重寫該方法,調用super並修改最後兩個rects的高度。爲了能夠修改它們,您需要創建UITextSelectionRect
的子類,因爲原始版本不可寫(請參閱此答案的結尾)。
長版本: 該方法在UITextView
中實現的方式很奇怪。以下是我想通通過試驗和錯誤:
如果你繼承的UITextView,並覆蓋這樣的方法:
- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
NSArray* result = [super selectionRectsForRange:range];
NSLog(@"%@", result);
return result;
}
,你會看到該方法返回一組跨越的選擇長方形的,但也兩個寬度爲零的矩形與光標的位置重合。有趣的是,改變數組的順序並不會對選擇或光標位置產生任何影響,所以不需要將這些長方形變成最後兩個,這是蘋果實現的細節。將它們一起移除會產生更有趣的效果:遊標不會消失,也不會執行任何選擇矩形。相反,光標取相鄰矩形的高度。當選擇一段文本時,這會導致跨越整個段落高度的光標。我的結論是,遊標將自己定位在選擇中的上層/最低層次的區域的高度和位置,蘋果實施-(NSArray *)selectionRectsForRange
通過插入零寬度的矩形來欺騙這個系統。這絕不是確定的,系統中可能存在一些更復雜的問題,涉及文本方向和其他怪癖。我在設備和模擬器上的iOS 8和10上測試了我的假設。
獎金這是我的可變UITextSelectionRect子類:
@interface RichTextSelectionRect : UITextSelectionRect
//Prefix everything with _ because the original names are marked as readonly in the superclass
@property (nonatomic) CGRect _rect;
@property (nonatomic) UITextWritingDirection _writingDirection;
@property (nonatomic) BOOL _containsStart; // Returns YES if the rect contains the start of the selection.
@property (nonatomic) BOOL _containsEnd; // Returns YES if the rect contains the end of the selection.
@property (nonatomic) BOOL _isVertical; // Returns YES if the rect is for vertically oriented text.
@end
@implementation RichTextSelectionRect
- (CGRect)rect{
return __rect;
}
- (UITextWritingDirection)writingDirection{
return __writingDirection;
}
- (BOOL)containsStart
{
return __containsStart;
}
- (BOOL)containsEnd
{
return __containsEnd;
}
- (BOOL)isVertical
{
return __isVertical;
}
@end
了大量的研究,我發現,我們可以覆蓋 '後 - (NSArray的*)selectionRectsForRange:(UITextRange *)range'和通過繼承'UITextSelectionView'我們可以設置範圍 – Padma