ios - 由于UITextView中的自定义行间距,导致文本选择无法正确进行

标签 ios cursor text-editor spacing textselection

我有一个应用了自定义行距的自定义UITextView。当我尝试选择文本时,selectionRect是错误的。 Check this image,突出显示正确,但是selectionRange起点和终点处的句柄大小错误。该特定行应用了50px的beforeSpacing和10px的afterSpacing。

相反,我希望它的行为像this

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

如何根据我的字体大小和所应用的行间距来修改selectionRect或选择句柄的大小?

最佳答案

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

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

如果您将UITextView子类化,并重写如下方法:

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

您将看到该方法返回一组跨选区的矩形,但还返回两个宽度为零且与光标位置一致的矩形。

有趣的是,更改数组的顺序不会对选择或光标位置产生任何影响,因此无需将这些矩形设置为最后两个矩形,这只是苹果实现的一个细节。一起删除它们会产生更有趣的效果:光标不会消失,选择矩形也不会消失。而是,光标占据相邻矩形的高度。选择文本的整个段落时,这会导致光标跨越整个段落的高度。我的结论是,光标将自身定向到所选内容中左上/右下矩形的高度和位置,Apples的-(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

关于ios - 由于UITextView中的自定义行间距,导致文本选择无法正确进行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38199591/

相关文章:

javascript - 在 mongodb 数据库中搜索特定字符串

python ,SQLite3 : cursor returns duplicates when a commit intervenes

android - 使用 Content Provider 更新数据库

c# - 有谁知道任何很酷的文本编辑程序可以轻松翻译代码?

ios - 比较两个图像以检查它们是否相同

ios - 应用程序运行时接到电话会调用哪个方法?

ios - 更新 cocoapods 库时 pod spec lint 或 pod lib lint 失败

ios - 使用迦太基时调试(拥有)框架

web-config - web.config 文件的轻量级编辑器

text - 如何在 Notepad++ 中显示列号?