由于UITextView中的自定义行间距,导致文本选择无法正确进行 [英] Text selection not happening properly because of custom line spacing in UITextView

查看:245
本文介绍了由于UITextView中的自定义行间距,导致文本选择无法正确进行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义 UITextView ,并应用了自定义行间距。当我尝试选择文本时, selectionRect 是错误的。 查看此图像,突出显示正确,但selectionRande范围的句柄大小为错误。特定的行应用了50px的beforeSpacing和10px的afterSpacing。

I have a custom UITextView with custom line spacing applied. When I try to select the text the selectionRect is wrong. Check this image where highlighting is correct but the size of the handles at selectionRange start and end is wrong. That particular line has beforeSpacing of 50px and afterSpacing of 10px applied.

相反,我希望它的行为类似于

Instead I want it to behave like this

我使用 caretRectForPosition修改了光标大小:并通过更改其rect来修改光标的位置和大小,但不幸的是,这不会影响选择期间的句柄。

I modified the cursor size using caretRectForPosition: and modified the position and size of the cursor by changing its rect, but unfortunately this does not affect the handles during selection.

如何修改selectionRect或

How do I modify the selectionRect or the size of the selection handles based on my font size and line spacing that is applied?

推荐答案

TL; DR:根据我的字体大小和行间距选择选择的大小?
您可以使用-(NSArray *)selectionRectsForRange ,它的行为很怪异,而且没有很好的记录。 UITextView 返回的最后两个矩形在调用-(NSArray *)selectionRectsForRange 时宽度为零,并确定高度开始游标和结束游标。创建一个子类,重写方法,调用super并修改最后两个矩形的高度。为了能够修改它们,您需要创建 UITextSelectionRect 的子类,因为原始版本不可写(请参见此答案的结尾)。

TL;DR: You can use -(NSArray *)selectionRectsForRange, which behaves weird and not documented very well. The last two rectangles returned by UITextView when calling -(NSArray *)selectionRectsForRange have zero width, and they determine the height of the begin and end cursors. Create a subclass, override the method, call super and modify the height of the last two rects. To be able to modify them, you need to create a subclass of UITextSelectionRect because the original version is not writable (see the end of this answer).

长版:
UITextView 中实现此方法的方法很奇怪。这是我通过反复试验得出的结论:

Long version: The way this method is implemented in UITextView is weird. Here is what I figured by trial and error:

如果您继承了UITextView,并重写了这样的方法:

If you subclass UITextView, and override the method like this:

- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
    NSArray* result = [super selectionRectsForRange:range];
    NSLog(@"%@", result);
    return result;
}

您将看到该方法返回了一组跨选区的矩形,但是还有两个宽度为零的矩形,它们与光标的位置重合。

you will see the method returns a set of rectangles that span the selection, but also two rectangles with width zero, that coincide with the location of the cursor.

足够有趣的是,更改数组的顺序对选择或选择不会产生任何影响。光标位置,因此不需要将这些矩形做成最后两个矩形,这是apples实现的一个细节。一起删除它们会产生更有趣的效果:光标不会消失,选择矩形也不会消失。而是,光标占据相邻矩形的高度。选择文本的整个段落时,这会导致光标跨越整个段落的高度。我的结论是,光标将其自身定向到所选内容中左上角/右下角矩形的高度和位置,并且Apple实现了-(NSArray *)selectionRectsForRange 通过插入零宽度矩形来欺骗该系统。这是绝对不确定的,并且在文本方向和其他怪癖方面,系统可能会更加复杂。我在设备上和模拟器中的iOS 8和10上测试了我的假设。

Interestingly enough, changing the order of the array does not have any impact on the selection or the cursor positions, so there is no need to make these rectangles the last two, it's rather a detail of apples implementation. Removing them all together has a more interesting effect: the cursors don't disappear, and neither do any of the selection rectangles. Rather, the cursors take the height of the adjacent rectangle. When selecting a whole paragraph of text, this leads to the cursors spanning the height of the whole paragraph. My conclusion is, that the cursors orient themselves towards the height and position of the upper-leftets/lower-rightest rects in the selection, and Apples implementation of -(NSArray *)selectionRectsForRange tricks this system by inserting zero-width rectangles. This is by no means certain, and there could be some more intricacies to the system, concerning text direction and other quirks. I tested my hypothesis on iOS 8 and 10 on device and in the simulator.

奖金,这是我可变的UITextSelectionRect子类:

Bonus this is my mutable UITextSelectionRect subclass:

@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中的自定义行间距,导致文本选择无法正确进行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆