首页显示富文本用的是textView控件,因为需要用到textView的selectionRectsForRange,有时候一个超链接或话题检测出来换行了,这时候就是两个矩形,而selectionRectsForRange就具有这个功能可以检测出某段文本的矩形数组,首先算出此富文本中有多少个链接Link(话题,超链接,@)
@interface LSLink : NSObject
@property (nonatomic, assign) NSRange range;
@property (nonatomic, copy) NSString *text;
/**
*对应的矩形框数组
*/
@property (nonatomic, strong) NSArray *rects;
@end
遍历富文本,取出之前添加的属性键值,如果为真则是一个Link,则创建一个LInk对象,设置link的text,和range然后利用textVeiw的selectionRectsForRange计算出这个范围对应的矩形框,但是返回的矩形框有的宽高为0则不添加到link.reces数组中,然后利用一个数组存放所有的Link
links是存放所有link的数组
-(NSMutableArray *)links
{
if (!_links) {
_links=[NSMutableArray array];
//遍历富文本
[self.attributedText enumerateAttributesInRange:NSMakeRange(0, self.attributedText.length) options:0 usingBlock:^(NSDictionary<NSString *,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
NSString *linkText=attrs[LSHighLink];
if (linkText==nil) return ;
//创建一个链接
LSLink *link=[[LSLink alloc]init];
link.range=range;
link.text=linkText;
//设置选中字符的范围
self.textView .selectedRange=range;
NSMutableArray *rects=[NSMutableArray array];
//算出选中字符的矩形框
NSArray *selectRects= [self.textView selectionRectsForRange:self.textView.selectedTextRange];
for (UITextSelectionRect *rect in selectRects) {
if (rect.rect.size.width==0||rect.rect.size.height==0)continue;
[rects addObject:rect];
}
link.rects=rects;
[_links addObject:link];
}];
self.textView.selectedRange=NSMakeRange(0, 0);
}
return _links;
}
当进行触摸事件时,遍历links数组,在遍历link.reces如果rect包含此point则返回此link,然后遍历此link.rects,在界面上添加几个小矩形,frame分别为link.rects的rect当touchend时移除所有添加的view
-(LSLink*)touchLickWithPoint:(CGPoint)point
{
__block LSLink *link=nil;
[self.links enumerateObjectsUsingBlock:^(LSLink * obj, NSUInteger idx, BOOL * _Nonnull stop) {
for (UITextSelectionRect *selectRect in obj.rects) {
if (CGRectContainsPoint(selectRect.rect, point)) {
link=obj;
break;
}
}
}];
return link;
}
显示高亮链接,设置tag为的是方便移除
-(void)showLinkBackgroud:(LSLink*)link
{
for (UITextSelectionRect *selectedRect in link.rects) {
UIView *bg=[[UIView alloc]init];
bg.frame=selectedRect.rect;
bg.tag=8888;
bg.layer.cornerRadius=4;
bg.backgroundColor=[UIColor colorWithRed:0 green:100/255.0 blue:100/255.0 alpha:0.2];
[self addSubview:bg];
}
}
移除所有高亮view
-(void)removeAllBgView
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
for (UIView *view in self.subviews) {
if (view.tag==8888) {
[view removeFromSuperview];
}
}
});
}
但是这样会点击整个textView当没有点钟超链接时不会处理别的事件,这时就需要一些底层的知识,当触摸屏幕时会调用以下两个方法
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 此方法返回YES为触摸点在自己身上才会调用一下方法
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 此方法返回nil即自己不处理事件,返回自己即处理事件
这时在hitTest方法里判根据point 是否能够得到link如果为真则自己处理,否则返回nil
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
LSLink *link= [self touchLickWithPoint:point];
if (link) {
return self;
}
else{
return nil;
}
}