将UITapGestureRecognizer添加到UILabel的特定部分的最佳方法是什么?

时间:2016-06-24 06:49:26

标签: ios objective-c uilabel nsattributedstring uitapgesturerecognizer

这个问题可能会问过几次,但我仍然在努力寻找最佳解决方案。带有NSMutableAttributedString的addAttributes将无法工作,因为我只能提供指向字符串一部分的链接。

我有一个标签,上面写着“已经注册?登录”。我可以获得NSRange文本“登录”,但我怎么能给它UITapGesture?我不想在这里使用第三方库。请给我一些想法。感谢

3 个答案:

答案 0 :(得分:1)

您无法将手势识别器添加到UILabel"的一部分。对于你的情况,我只会使用两个不同的UILabel:一个是不可用的,表示"已经注册了?",还有一个可以说是"在这里登录" 。老实说,我将可点击的部分放入UIButton中以使其清晰。还有一个选择是将空UIView作为UILabel的子视图,使其成为您想要点击的文本的大小。然后将手势识别器添加到该子视图中。

(在我看来,开发人员在使用iOS时遇到的最大陷阱之一是试图强迫它采取与设计不同的行为;比如模仿网络链接或其他东西。它总是效果最好,而且代码最少,写的时候要利用它的设计模式)

可以忽略所有抽头位置无意义,因为这是识别器的要点。识别器会为您处理所有这些,并且会在点击UIView时使用您设置的操作调用目标。

所以它基本上是:

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:someObject action:@selector(someMethod:)];
[loginLabel addGestureRecognizer:tapRecognizer];

就是这样。其余的将由系统为您处理。点击标签时将调用目标对象。至少,从原帖中描述的问题来看似乎很简单。如果还有其他并发症,请在您的问题中加入这些要点。

答案 1 :(得分:0)

手势识别器无法添加到UI组件的特定部分。 但是,在内部点按处理程序操作中,您可能需要检查

CGPoint tapLocation = [tapRecognizer locationInView:tapRecognizer.view];

您可以查看该点是否在targetRect

if(CGRectContainsPoint(myTargetRect, tapLocation))
{
    // Do your action here
}

希望它有所帮助。

更新

根据需要,来自@Code的答案中的getRect()的Objective-C版本。

-(CGRect)getRectForString:(NSAttributedString*)str withRange:(NSRange)textRange usingMaxWidth:(CGFloat)maxWidth
{
    // Create a layoutManager
    NSLayoutManager* layoutManager = [[NSLayoutManager alloc] init];

    // Create a textContainer with maxWidth size and add it to layoutManager
    NSTextContainer* textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(maxWidth, CGFLOAT_MAX)];
    [layoutManager addTextContainer:textContainer];
    textContainer.lineFragmentPadding = 0;

    // Create a textStorage with 'str' variable and add the layoutManager to this textStorage
    NSTextStorage* textStorage = [[NSTextStorage alloc] initWithAttributedString:str];
    [textStorage addLayoutManager:layoutManager];

    // Query the actualGlyphRange from layoutManager for specified textRange
    NSRange actualGlyphRange;
    [layoutManager characterRangeForGlyphRange:textRange actualGlyphRange:&actualGlyphRange];

    // Find out the boundingRect for actualGlyphRange
    return [layoutManager boundingRectForGlyphRange:actualGlyphRange inTextContainer:textContainer];
}

答案 2 :(得分:0)

你不能将敲击手势添加到UILabel的特定部分,或者如果你试图这样做,你将坚持寻找可能对你有所帮助的框架和标签的一部分,但如果是这样的话会更有问题在UITableViewCell等其他视图中。对于父/子视图,可能需要对点转换进行一些计算。

为了简单起见,我的建议是创建一个UIView,其中嵌入了UILabelUIButton,按钮设置在UILabel旁边。

一个例子:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

     // Create label
     UILabel *lbl = [[UILabel alloc] init];
    [lbl setText:@"Already Sign up ? "];
    [lbl sizeToFit];

     // Create button
     UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    [btn setTitle:@"Login Here" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(didTapLink:) forControlEvents:UIControlEventTouchUpInside];
    [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [btn sizeToFit];
    [btn setFrame:CGRectMake(lbl.frame.size.width, lbl.frame.origin.y, btn.frame.size.width, lbl.frame.size.height)];

     // Create container that embeds the label and button
     UIView *customLabel = [[UIView alloc] initWithFrame:CGRectMake(0, 50, lbl.frame.size.width + btn.frame.size.width, lbl.frame.size.height)];
    [customLabel addSubview:lbl];
    [customLabel addSubview:btn];

     // Add this custom label to UI
    [self.view addSubview:customLabel];
}

-(void)didTapLink:(id)sender
{
    NSLog(@"Button tapped");
}

截图:

enter image description here

希望有所帮助!