由于 UITextView 中的自定义行距,文本选择不正确
Posted
技术标签:
【中文标题】由于 UITextView 中的自定义行距,文本选择不正确【英文标题】:Text selection not happening properly because of custom line spacing in UITextView 【发布时间】:2016-11-07 01:32:02 【问题描述】:我有一个自定义的UITextView
应用了自定义行距。当我尝试选择文本时,selectionRect
是错误的。 Check this image 突出显示正确,但 selectionRange 开始和结束处的句柄大小错误。该特定行应用了 50px 的 beforeSpacing 和 10px 的 afterSpacing。
相反,我希望它表现得像 this
我使用caretRectForPosition:
修改了光标大小,并通过更改其矩形来修改光标的位置和大小,但不幸的是这不会影响选择期间的手柄。
如何根据我应用的字体大小和行距修改 selectionRect 或选择句柄的大小?
【问题讨论】:
经过大量研究,我发现我们可以覆盖-(NSArray*)selectionRectsForRange:(UITextRange *)range
,并通过继承UITextSelectionView
,我们可以为范围设置自定义selectionRect
【参考方案1】:
TL;DR:
您可以使用-(NSArray *)selectionRectsForRange
,它的行为很奇怪并且没有很好地记录。 UITextView
在调用-(NSArray *)selectionRectsForRange
时返回的最后两个矩形宽度为零,它们决定了开始和结束光标的高度。创建一个子类,重写方法,调用 super 并修改最后两个矩形的高度。为了能够修改它们,您需要创建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
【讨论】:
谢谢 :) 我想通了以上是关于由于 UITextView 中的自定义行距,文本选择不正确的主要内容,如果未能解决你的问题,请参考以下文章