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

Posted

技术标签:

【中文标题】将 UITapGestureRecognizer 添加到 UILabel 的特定部分的最佳方法是啥?【英文标题】:What is the best way to add UITapGestureRecognizer to a specific part of UILabel?将 UITapGestureRecognizer 添加到 UILabel 的特定部分的最佳方法是什么? 【发布时间】:2016-06-24 06:49:25 【问题描述】:

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

我有一个带有字符串“已经注册?在此处登录”的标签。我可以得到文本“登录”的 NSRange,但我怎样才能给它 UITapGesture?我不想在这里使用 3rd 方库。请给我一些想法。谢谢

【问题讨论】:

你为什么不使用UITextView?它可以自定义为看起来像“正常”UILabel 【参考方案1】:

您不能将手势识别器添加到“UILabel 的一部分”。对于您的情况,我将只使用两种不同的 UILabel:一种是不可点击的,表示“已经注册?”,另一种是可点击的,表示“在此处登录”。老实说,我会将可点击部分放入 UIButton 中以使其清楚。另一种选择是将空的 UIView 作为 UILabel 的子视图,使其成为您要点击的文本的大小。然后将手势识别器添加到那个子视图。

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

所有点击位置的废话都可以忽略,因为那是识别器的重点。识别器会为您处理所有这些,并会在点击 UIView 时使用您设置的操作调用您的目标。

所以基本上是这样的:

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

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

【讨论】:

【参考方案2】:

手势识别器不能添加到 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];

【讨论】:

是的,它有帮助,但我怎样才能得到“myTargetRect”,这是这里的主要问题。 查看这个答案 ***.com/a/38007419/6458001 getRect() 就是你要找的。​​span> 目标 c 是我正在寻找的。 Swift 尚待学习。如果您可以将其转换为目标 c,将不胜感激 更新了答案。 @HirenPrajapati 如果该解决方案适合您,您应该将其标记为答案。它将帮助其他开发人员在搜索与您遇到的相同问题时做出选择。【参考方案3】:

您无法将轻击手势添加到 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");

截图:

希望有帮助!

【讨论】:

以上是关于将 UITapGestureRecognizer 添加到 UILabel 的特定部分的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

将 NSDictionary 作为参数传递给 UITapGestureRecognizer

将 UITapGestureRecognizer 添加到 UIControl

将 UITapGestureRecognizer 连接到 UIView

将 UITapGestureRecognizer 触摸传递到底层 UITableViewCell

将 UITapGestureRecognizer 添加到 XIB

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