UITextView 应该检测链接,否则应该将触摸传播到下面的视图
UITextView should detect links, but otherwise, should propagate touch to view below
我有一个文本视图,我想在其中检测 links,但是当触摸点没有 link 时,它应该将触摸传播到下面的视图(它目前没有)。它将包含在 table 视图单元格中,如果用户点击 link,它应该交互(有效),但是当点击另一个点时,它应该 select table查看单元格。
我需要文本不select可用,所以我遵循了并实现了:
-(BOOL)canBecomeFirstResponder{
return NO;
}
在此之前它也没有发送下面的触摸事件,但我将它包括在内只是为了防止它干扰解决方案。
而不是阻止您的文本视图成为第一响应者,您需要子类化 hitTest
方法,以便它 return 在 link 中发生点击时它是 textView 并且return 否则为零。
@interface LinkOnlyTextView : UITextView
@end
@implementation LinkOnlyTextView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSUInteger glyphIndex = [self.layoutManager glyphIndexForPoint:point inTextContainer:self.textContainer fractionOfDistanceThroughGlyph:nullptr];
NSUInteger characterIndex = [self.layoutManager characterIndexForGlyphAtIndex:glyphIndex];
if (characterIndex < self.textStorage.length) {
if ([self.textStorage attribute:NSLinkAttributeName atIndex:characterIndex effectiveRange:nullptr]) {
return self;
}
}
return nil;
}
@end
此代码片段的 Swift 版本由 @blwinters 提供,稍后在此处回答此问题:
这是@Dalzhim 答案的 Swift 版本,合并了@jupham 的调整以检查 point
实际上包含在 glyphRect
.
中
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let glyphIndex = self.layoutManager.glyphIndex(for: point, in: self.textContainer)
//Ensure the glyphIndex actually matches the point and isn't just the closest glyph to the point
let glyphRect = self.layoutManager.boundingRect(forGlyphRange: NSRange(location: glyphIndex, length: 1), in: self.textContainer)
if glyphIndex < self.textStorage.length,
glyphRect.contains(point),
self.textStorage.attribute(NSAttributedStringKey.link, at: glyphIndex, effectiveRange: nil) != nil {
return self
} else {
return nil
}
}
我有一个文本视图,我想在其中检测 links,但是当触摸点没有 link 时,它应该将触摸传播到下面的视图(它目前没有)。它将包含在 table 视图单元格中,如果用户点击 link,它应该交互(有效),但是当点击另一个点时,它应该 select table查看单元格。
我需要文本不select可用,所以我遵循了并实现了:
-(BOOL)canBecomeFirstResponder{
return NO;
}
在此之前它也没有发送下面的触摸事件,但我将它包括在内只是为了防止它干扰解决方案。
而不是阻止您的文本视图成为第一响应者,您需要子类化 hitTest
方法,以便它 return 在 link 中发生点击时它是 textView 并且return 否则为零。
@interface LinkOnlyTextView : UITextView
@end
@implementation LinkOnlyTextView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSUInteger glyphIndex = [self.layoutManager glyphIndexForPoint:point inTextContainer:self.textContainer fractionOfDistanceThroughGlyph:nullptr];
NSUInteger characterIndex = [self.layoutManager characterIndexForGlyphAtIndex:glyphIndex];
if (characterIndex < self.textStorage.length) {
if ([self.textStorage attribute:NSLinkAttributeName atIndex:characterIndex effectiveRange:nullptr]) {
return self;
}
}
return nil;
}
@end
此代码片段的 Swift 版本由 @blwinters 提供,稍后在此处回答此问题:
这是@Dalzhim 答案的 Swift 版本,合并了@jupham 的调整以检查 point
实际上包含在 glyphRect
.
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let glyphIndex = self.layoutManager.glyphIndex(for: point, in: self.textContainer)
//Ensure the glyphIndex actually matches the point and isn't just the closest glyph to the point
let glyphRect = self.layoutManager.boundingRect(forGlyphRange: NSRange(location: glyphIndex, length: 1), in: self.textContainer)
if glyphIndex < self.textStorage.length,
glyphRect.contains(point),
self.textStorage.attribute(NSAttributedStringKey.link, at: glyphIndex, effectiveRange: nil) != nil {
return self
} else {
return nil
}
}