iOS UITextView或UILabel,带有可单击的动作链接 [英] iOS UITextView or UILabel with clickable links to actions

查看:101
本文介绍了iOS UITextView或UILabel,带有可单击的动作链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个 UILabel UITextView ,其中包含一些带有2个可点击链接的文字。不是指向网页的链接,但我想将这两个链接与我用 UIButton 这样的操作相关联。我见过的所有例子都是webviews的链接,但我不想这样。同样,文本将被翻译成其他语言,因此位置必须是动态的。

I want to make a UILabel or UITextView with some text with 2 clickable links in it. Not links to webpages but I want to link those 2 links with actions like i would do with an UIButton. All the examples i've seen are links to webviews but I dont want that. As well, the text will be translated in other languages so the positions have to be dynamic.

想要这样做:

推荐答案

我需要解决这个完全相同的问题:非常相似的文本与其中的两个链接,多行,并且需要它能够以任何语言翻译(包括不同的单词顺序,等等)。我刚解决了,所以让我分享一下我是如何做到的。

I needed to solve this exact same problem: very similar text with those two links in it, over multiple lines, and needing it to be able to be translated in any language (including different word orders, etc). I just solved it, so let me share how I did it.

最初我认为我应该创建属性文本,然后将tap的触摸位置映射到其中的区域那个文字。虽然我认为这是可行的,但我也认为这是一个非常复杂的方法。

Initially I was thinking that I should create attributed text and then map the tap's touch location to the regions within that text. While I think that is doable, I also think it's a much too complicated approach.

这就是我最终做的事情:

This is what I ended up doing instead:

摘要:


  • 在您的英文邮件中有非常基本的自定义标记,以便您可以解析不同的部分

  • 指示您的译员留下标记并翻译其余部分

  • 拥有一个可作为此消息容器的UIView

  • 将您的英文消息分成几部分以将常规文本与可点击文本分开

  • 为每件作品在容器UIView上创建UILabel

  • 对于可点击的作品,设置您的样式,允许用户交互并创建您的轻拍手势识别器

  • 做一些非常基本的簿记,将单词完美地放在行

  • Have very basic custom markup in your English message so you can parse out the different pieces
  • Instruct your translators to leave the markup in and translate the rest
  • Have a UIView that can serve as the container of this message
  • Break your English message up in pieces to separate the regular text from the clickable text
  • For each piece create a UILabel on the container UIView
  • For the clickable pieces, set your styling, allow user interaction and create your tap gesture recognizer
  • Do some very basic bookkeeping to place the words perfectly across the lines

详细信息:

在查看控制器的 viewDidLoad 我放置了这个:

In the view controller's viewDidLoad I placed this:

[self buildAgreeTextViewFromString:NSLocalizedString(@"I agree to the #<ts>terms of service# and #<pp>privacy policy#", 
                                                     @"PLEASE NOTE: please translate \"terms of service\" and \"privacy policy\" as well, and leave the #<ts># and #<pp># around your translations just as in the English version of this message.")];

我正在调用一个构建消息的方法。注意我提出的标记。你当然可以创造自己的,但关键是我也标记每个可点击区域的末端,因为它们跨越多个单词。

I'm calling a method that will build the message. Note the markup I came up with. You can of course invent your own, but key is that I also mark the ends of each clickable region because they span over multiple words.

以下是将消息放在一起的方法 - 见下文。首先,我通过字符(或者更确切地说 @#字符串)分解英文消息。这样我就可以分别创建一个标签。我循环遍历它们并寻找我的基本标记< ts> < pp> 来检测哪些碎片是什么的链接。如果我正在处理的文本块是一个链接,那么我会设置一个样式并为其设置一个轻敲手势识别器。我当然也删除了标记字符。我认为这是一个非常简单的方法。

Here's the method that puts the message together -- see below. First I break up the English message over the # character (or rather @"#" string). That way I get each piece for which I need to create a label separately. I loop over them and look for my basic markup of <ts> and <pp> to detect which pieces are links to what. If the chunk of text I'm working with is a link, then I style a bit and set up a tap gesture recogniser for it. I also strip out the markup characters of course. I think this is a really easy way to do it.

注意一些细微之处,比如我如何处理空格:我只是从(本地化)字符串中取出空格。如果没有空格(中文,日文),则块之间也不会有空格。如果有空格,那么它们会根据需要自动分隔出块(例如英语)。当我必须在下一行的开头放置一个单词时,我确实需要确保从该文本中删除任何空格前缀,否则它将无法正确对齐。

Note some subtleties like how I handle spaces: I simply take the spaces from the (localised) string. If there are no spaces (Chinese, Japanese), then there won't be spaces between the chunks either. If there are spaces, then those automatically space out the chunks as needed (e.g. for English). When I have to place a word at the start of a next line though, then I do need to make sure that I strip of any white space prefix from that text, because otherwise it doesn't align properly.

- (void)buildAgreeTextViewFromString:(NSString *)localizedString
{
  // 1. Split the localized string on the # sign:
  NSArray *localizedStringPieces = [localizedString componentsSeparatedByString:@"#"];

  // 2. Loop through all the pieces:
  NSUInteger msgChunkCount = localizedStringPieces ? localizedStringPieces.count : 0;
  CGPoint wordLocation = CGPointMake(0.0, 0.0);
  for (NSUInteger i = 0; i < msgChunkCount; i++)
  {
    NSString *chunk = [localizedStringPieces objectAtIndex:i];
    if ([chunk isEqualToString:@""])
    {
      continue;     // skip this loop if the chunk is empty
    }

    // 3. Determine what type of word this is:
    BOOL isTermsOfServiceLink = [chunk hasPrefix:@"<ts>"];
    BOOL isPrivacyPolicyLink  = [chunk hasPrefix:@"<pp>"];
    BOOL isLink = (BOOL)(isTermsOfServiceLink || isPrivacyPolicyLink);

    // 4. Create label, styling dependent on whether it's a link:
    UILabel *label = [[UILabel alloc] init];
    label.font = [UIFont systemFontOfSize:15.0f];
    label.text = chunk;
    label.userInteractionEnabled = isLink;

    if (isLink)
    {
      label.textColor = [UIColor colorWithRed:110/255.0f green:181/255.0f blue:229/255.0f alpha:1.0];
      label.highlightedTextColor = [UIColor yellowColor];

      // 5. Set tap gesture for this clickable text:
      SEL selectorAction = isTermsOfServiceLink ? @selector(tapOnTermsOfServiceLink:) : @selector(tapOnPrivacyPolicyLink:);
      UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                   action:selectorAction];
      [label addGestureRecognizer:tapGesture];

      // Trim the markup characters from the label:
      if (isTermsOfServiceLink) 
        label.text = [label.text stringByReplacingOccurrencesOfString:@"<ts>" withString:@""];
      if (isPrivacyPolicyLink)  
        label.text = [label.text stringByReplacingOccurrencesOfString:@"<pp>" withString:@""];
    }
    else
    {
      label.textColor = [UIColor whiteColor];
    }

    // 6. Lay out the labels so it forms a complete sentence again:

    // If this word doesn't fit at end of this line, then move it to the next
    // line and make sure any leading spaces are stripped off so it aligns nicely:

    [label sizeToFit];

    if (self.agreeTextContainerView.frame.size.width < wordLocation.x + label.bounds.size.width)
    {
      wordLocation.x = 0.0;                       // move this word all the way to the left...
      wordLocation.y += label.frame.size.height;  // ...on the next line

      // And trim of any leading white space:
      NSRange startingWhiteSpaceRange = [label.text rangeOfString:@"^\\s*"
                                                          options:NSRegularExpressionSearch];
      if (startingWhiteSpaceRange.location == 0)
      {
        label.text = [label.text stringByReplacingCharactersInRange:startingWhiteSpaceRange
                                                         withString:@""];
        [label sizeToFit];
      }
    }

    // Set the location for this label:
    label.frame = CGRectMake(wordLocation.x,
                             wordLocation.y,
                             label.frame.size.width,
                             label.frame.size.height);
    // Show this label:
    [self.agreeTextContainerView addSubview:label];

    // Update the horizontal position for the next word:
    wordLocation.x += label.frame.size.width;
  }
}

这是我处理检测到的水龙头的方法那些链接。

And here are my methods that handle the detected taps on those links.

- (void)tapOnTermsOfServiceLink:(UITapGestureRecognizer *)tapGesture
{
  if (tapGesture.state == UIGestureRecognizerStateEnded)
  {
    NSLog(@"User tapped on the Terms of Service link");
  }
}


- (void)tapOnPrivacyPolicyLink:(UITapGestureRecognizer *)tapGesture
{
  if (tapGesture.state == UIGestureRecognizerStateEnded)
  {
    NSLog(@"User tapped on the Privacy Policy link");
  }
}

希望这会有所帮助。我确信有更聪明,更优雅的方法可以做到这一点,但这是我能够提出的并且效果很好。

Hope this helps. I'm sure there are much smarter and more elegant ways to do this, but this is what I was able to come up with and it works nicely.

这是怎么回事在应用程序中查找:

Here's how it looks in the app:

祝你好运! : - )

Good luck! :-)

Erik

这篇关于iOS UITextView或UILabel,带有可单击的动作链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆