iOS:使用可单击的标签和用户名创建文本区域
我试图创建一个包含可点击的hashtags(#abc)和用户名(@xyz)的文本视图。最初,我将UILabel子类化,尽管我已使其正常工作,但只有当文本的范围小于中的102个字符时,该区域才可单击(下面的boundingRectForCharacterRange函数开始返回{0,0}) 接下来,我尝试将UITextView子类化,它将此限制增加到大约300个字符,但仍然存在相同的问题 有人知道我如何提高这个限制吗?我最多使用1000个字符 我的子类UITextView代码如下(我知道我还没有完成协议部分,但希望您能了解我的问题…): ClickableTextView.hiOS:使用可单击的标签和用户名创建文本区域,ios,objective-c,xcode,uilabel,uitextview,Ios,Objective C,Xcode,Uilabel,Uitextview,我试图创建一个包含可点击的hashtags(#abc)和用户名(@xyz)的文本视图。最初,我将UILabel子类化,尽管我已使其正常工作,但只有当文本的范围小于中的102个字符时,该区域才可单击(下面的boundingRectForCharacterRange函数开始返回{0,0}) 接下来,我尝试将UITextView子类化,它将此限制增加到大约300个字符,但仍然存在相同的问题 有人知道我如何提高这个限制吗?我最多使用1000个字符 我的子类UITextView代码如下(我知道我还没有完成
#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
ViewController.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
#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
请帮忙 为什么不直接使用
ui按钮
?谢谢你的回复,彼得。文本是动态的,所以我永远不知道可点击的链接会在哪里。如果我这样做的话,我仍然需要得到hashtag/username文本的边界cgrit,这是不起作用的部分。您是否尝试过使用IFTweetLabel..在label@Vidhyanand900,谢谢你的提醒,但我希望能解决我的问题。我想自己做这件事,这样我可以在将来定制它,因为我喜欢从我的错误/缺点中学习:)有什么想法吗?@Damien你解决了吗?关于内容不断变化的文本视图,我也面临着同样的问题。。。我的第一个想法是定义操作键:@、#、删除、返回、纯文本和粘贴操作,将它们放在json中,并存储在一个可变数组中,类型为:hashTag、userName、brakeLine和plainText。通过切换json中的最后一个类型和确定更改类型、追加字符串或删除最后一个json的操作。我还在努力,希望也能听到你的声音:)