我想做一个UILabelUITextView与一些文本中的2个可点击的链接.不是到网页的链接,但我想把这2个链接与行动链接起来,就像我用UIButton做的那样.我看到的所有例子都是到网络视图的链接,但我不想要这样的链接.此外,文本将被翻译成其他语言,因此位置必须是动态的.

想要做到这一点:

在此处输入图像描述

推荐答案

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

最初我想我应该创建属性文本,然后将点击的touch 位置映射到文本中的区域.虽然我认为这是可行的,但我也认为这是一种过于复杂的方法.

这就是我最终要做的:

SUMMARY:

  • 在你的英语信息中有非常基本的自定义标记,这样你就可以解析出不同的部分
  • 指示您的翻译人员将标记留在其中并翻译睡觉
  • 具有可用作此邮件容器的UIView
  • 将您的英文消息分成几个部分,以便将常规文本与可点击文本分开
  • 对于每一块,在容器UIView上创建一个UILabel
  • 对于可点击的部分,设置样式,允许用户交互,并创建点击手势识别器
  • 做一些非常基本的簿记,将单词完美地放在横线上

DETAIL:

在视图控制器的viewDidLoad中,我放置了以下内容:

[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.")];

我正在调用一个将生成消息的方法.注意我提出的标记.你当然可以发明自己的,但关键是我还标记了每个可点击区域的末端,因为它们跨越多个单词.

下面是将消息组合在一起的方法--请参见下面的内容.首先,我将英文消息分解为#个字符(或者更确切地说,是@"#"个字符串).这样,我就可以得到需要单独创建标签的每一件东西.我循环遍历它们并查找<ts><pp>的基本标记,以检测哪些部分是指向什么的链接.如果我正在处理的文本块是一个链接,那么我会设置一些样式,并为它设置一个点击手势识别器.当然,我还go 掉了标记字符.我认为这是一种非常简单的方法.

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

- (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;
  }
}

下面是我处理在这些链接上检测到的点击的方法.

- (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");
  }
}

希望这有帮助.我相信有很多更聪明、更优雅的方法可以做到这一点,但这正是我能想到的,而且效果很好.

以下是它在应用程序中的外观:

最终结果的模拟器屏幕快照

祝你好运!:-)

埃里克

Ios相关问答推荐

Flutter中抛出后期应用错误

IOS:在UI线程中执行代码的闭包样式的替代

分配给指针会通过 class_addMethod 导致 EXC_BAD_ACCESS

无法关闭包含字体 Select 器的工作表

无法向委托发送数据

为什么applicationState发布者只发布一次?

如何通过点击按钮滚动到 ScrollView 中的特定视图?

SwiftUI - TextField - 在焦点上清除 Double 类型的值,在取消 Select 时恢复

如何在应用程序中显示我的小部件的快照?

xcode-select:找不到clang

从iOS键盘输入时Flutter TextField输入消失

小部件链接有效,但不执行任何操作

在所有 tableview / collectionview 中禁用滚动指示器

SwiftUI DatePicker 格式在每个设备上都不一样,如何让它总是显示相同的 Select 版本?

如何使用情节提要重新排列 UITabBarController 项目?

CocoaPods 找不到 podFirebase/Core的兼容版本 | cloud_firestore, Flutter

通过touch 传递到下面的 UIViews

UITextView 内容插图

为给定的 UIColor 获取更亮和更暗的 colored颜色 变化

如何为 iOS 13 的 SF Symbols 设置权重?