由于 UITextView 中的自定义行间距,文本选择不正确
Text selection not happening properly because of custom line spacing in UITextView
我有一个应用了自定义行距的自定义 UITextView
。当我尝试 select 文本时 selectionRect
是错误的。 Check this image 其中突出显示是正确的,但 selectionRange 开始和结束处的句柄大小是错误的。该特定行应用了 50px 的 beforeSpacing 和 10px 的 afterSpacing。
相反,我希望它表现得像 this
我使用 caretRectForPosition:
修改了光标大小,并通过更改其矩形修改了光标的位置和大小,但不幸的是,这不会影响 selection 期间的句柄。
如何根据我应用的字体大小和行间距修改 selectionRect 或 selection 句柄的大小?
长话短说:
您可以使用 -(NSArray *)selectionRectsForRange
,它的行为很奇怪并且没有很好地记录。调用 -(NSArray *)selectionRectsForRange
时 UITextView
返回的最后两个矩形的宽度为零,它们决定了开始和结束游标的高度。创建一个子类,覆盖方法,调用super并修改最后两个rects的高度。为了能够修改它们,您需要创建 UITextSelectionRect
的子类,因为原始版本不可写(请参阅此答案的末尾)。
长版:
这个方法在UITextView
中的实现方式很奇怪。这是我通过反复试验得出的结论:
如果您将 UITextView 子类化,并重写这样的方法:
- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
NSArray* result = [super selectionRectsForRange:range];
NSLog(@"%@", result);
return result;
}
您将看到方法 returns 一组横跨选区的矩形,还有两个宽度为零且与光标位置重合的矩形。
有趣的是,更改数组的顺序对选择或光标位置没有任何影响,因此无需将这些矩形设为最后两个,而是 apples 实现的细节。将它们一起移除会产生更有趣的效果:光标不会消失,任何选择矩形也不会消失。相反,光标采用相邻矩形的高度。选择整段文本时,这会导致光标跨越整段的高度。我的结论是,光标将自己定向到选择中 upper-leftets/lower-rightest 矩形的高度和位置,Apple 的 -(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
。当我尝试 select 文本时 selectionRect
是错误的。 Check this image 其中突出显示是正确的,但 selectionRange 开始和结束处的句柄大小是错误的。该特定行应用了 50px 的 beforeSpacing 和 10px 的 afterSpacing。
相反,我希望它表现得像 this
我使用 caretRectForPosition:
修改了光标大小,并通过更改其矩形修改了光标的位置和大小,但不幸的是,这不会影响 selection 期间的句柄。
如何根据我应用的字体大小和行间距修改 selectionRect 或 selection 句柄的大小?
长话短说:
您可以使用 -(NSArray *)selectionRectsForRange
,它的行为很奇怪并且没有很好地记录。调用 -(NSArray *)selectionRectsForRange
时 UITextView
返回的最后两个矩形的宽度为零,它们决定了开始和结束游标的高度。创建一个子类,覆盖方法,调用super并修改最后两个rects的高度。为了能够修改它们,您需要创建 UITextSelectionRect
的子类,因为原始版本不可写(请参阅此答案的末尾)。
长版:
这个方法在UITextView
中的实现方式很奇怪。这是我通过反复试验得出的结论:
如果您将 UITextView 子类化,并重写这样的方法:
- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
NSArray* result = [super selectionRectsForRange:range];
NSLog(@"%@", result);
return result;
}
您将看到方法 returns 一组横跨选区的矩形,还有两个宽度为零且与光标位置重合的矩形。
有趣的是,更改数组的顺序对选择或光标位置没有任何影响,因此无需将这些矩形设为最后两个,而是 apples 实现的细节。将它们一起移除会产生更有趣的效果:光标不会消失,任何选择矩形也不会消失。相反,光标采用相邻矩形的高度。选择整段文本时,这会导致光标跨越整段的高度。我的结论是,光标将自己定向到选择中 upper-leftets/lower-rightest 矩形的高度和位置,Apple 的 -(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