我正在尝试使用包含可点击主题标签(#abc)和用户名(@xyz)的文本创建视图。最初我将UILabel子类化了,虽然我得到了它的工作,但是如果文本的范围小于102个字符(下面的boundingRectForCharacterRange函数开始返回{0,0}),则该区域只能被点击。
接下来,我尝试将UITextView子类化,并将此限制增加到大约300个字符,但仍然存在同样的问题。
任何人对如何增加此限制有任何想法?我最多使用1000个字符。
我的子类UITextView代码如下(我知道我还没有完成协议位,但希望你能解决我的问题......):
ClickableTextView.h
#import <UIKit/UIKit.h>
@protocol ClickableTextViewDelegate <NSObject>
@required
- (void)hashTagPressed:(NSString*)hashtagName;
- (void)usernamePressed:(NSString*)username;
@end
@interface ClickableTextView : UITextView
{
NSMutableArray *hashtags;
NSMutableArray *usernames;
UIColor *clickableColor;
//id <ClickableTextViewDelegate> labelDelegate;
}
//@property (nonatomic,strong) id labelDelegate;
- (void)setClickableColor:(UIColor*)color;
@end
ClickableTextView.m
#import "ClickableTextView.h"
@implementation ClickableTextView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
clickableColor = [UIColor blueColor];
self.userInteractionEnabled = YES;
self.editable = NO;
self.scrollEnabled = NO;
self.textContainerInset = UIEdgeInsetsZero;
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondToTapGesture:)];
tapRecognizer.numberOfTapsRequired = 1;
[self addGestureRecognizer:tapRecognizer];
}
return self;
}
- (void)setText:(NSString*)text
{
[super setText:text];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:text];
[self setAttributedText:attrString];
if(!hashtags) {
hashtags = [NSMutableArray array];
}
if(!usernames) {
usernames = [NSMutableArray array];
}
[hashtags removeAllObjects];
[usernames removeAllObjects];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"#(\\w+)" options:0 error:nil];
NSArray *matches = [regex matchesInString:text options:0 range:NSMakeRange(0, text.length)];
for(NSTextCheckingResult *match in matches) {
NSRange tagRange = [match rangeAtIndex:1];
tagRange.location--;
tagRange.length++;
[attrString addAttribute:NSForegroundColorAttributeName value:clickableColor range:tagRange];
CGRect tagRect = [self boundingRectForCharacterRange:tagRange];
[hashtags addObject:[NSDictionary dictionaryWithObjects:@[[text substringWithRange:tagRange], [NSNumber numberWithInt:tagRect.origin.x], [NSNumber numberWithInt:tagRect.origin.y], [NSNumber numberWithInt:tagRect.size.width], [NSNumber numberWithInt:tagRect.size.height]] forKeys:@[@"text", @"x", @"y", @"width", @"height"]]];
}
regex = [NSRegularExpression regularExpressionWithPattern:@"@(\\w+)" options:0 error:nil];
matches = [regex matchesInString:text options:0 range:NSMakeRange(0, text.length)];
for(NSTextCheckingResult *match in matches) {
NSRange userRange = [match rangeAtIndex:1];
userRange.location--;
userRange.length++;
[attrString addAttribute:NSForegroundColorAttributeName value:clickableColor range:userRange];
CGRect userRect = [self boundingRectForCharacterRange:userRange];
[usernames addObject:[NSDictionary dictionaryWithObjects:@[[text substringWithRange:userRange], [NSNumber numberWithInt:userRect.origin.x], [NSNumber numberWithInt:userRect.origin.y], [NSNumber numberWithInt:userRect.size.width], [NSNumber numberWithInt:userRect.size.height]] forKeys:@[@"text", @"x", @"y", @"width", @"height"]]];
}
[self setAttributedText:attrString];
[self sizeToFit];
}
- (CGRect)boundingRectForCharacterRange:(NSRange)range
{
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:[self attributedText]];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:[self bounds].size];
[layoutManager addTextContainer:textContainer];
NSRange glyphRange;
[layoutManager characterRangeForGlyphRange:range actualGlyphRange:&glyphRange];
return [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
}
- (void)respondToTapGesture:(UITapGestureRecognizer*)recognizer
{
CGPoint point = [recognizer locationInView:self];
for(NSDictionary *hashtag in hashtags) {
CGRect tagRect = CGRectMake([[hashtag objectForKey:@"x"] floatValue], [[hashtag objectForKey:@"y"] floatValue], [[hashtag objectForKey:@"width"] floatValue], [[hashtag objectForKey:@"height"] floatValue]);
if(CGRectContainsPoint(tagRect, point)) {
NSLog(@"Hashtag: %@", [hashtag objectForKey:@"text"]);
}
}
for(NSDictionary *username in usernames) {
CGRect userRect = CGRectMake([[username objectForKey:@"x"] floatValue], [[username objectForKey:@"y"] floatValue], [[username objectForKey:@"width"] floatValue], [[username objectForKey:@"height"] floatValue]);
if(CGRectContainsPoint(userRect, point)) {
NSLog(@"Username: %@", [username objectForKey:@"text"]);
}
}
}
- (void)setClickableColor:(UIColor*)color
{
clickableColor = color;
if(self.text) {
[self setText:self.text];
}
}
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ClickableTextView *textView = [[ClickableTextView alloc] initWithFrame:CGRectMake(50, 100, self.view.frame.size.width - 100, 100)];
textView.text = @"A #quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A #quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quiiiiiiick #test";
[self.view addSubview:textView];
}
@end
请帮忙!