我想做一个UILabel
或UITextView
与一些文本中的2个可点击的链接.不是到网页的链接,但我想把这2个链接与行动链接起来,就像我用UIButton
做的那样.我看到的所有例子都是到网络视图的链接,但我不想要这样的链接.此外,文本将被翻译成其他语言,因此位置必须是动态的.
想要做到这一点:
我想做一个UILabel
或UITextView
与一些文本中的2个可点击的链接.不是到网页的链接,但我想把这2个链接与行动链接起来,就像我用UIButton
做的那样.我看到的所有例子都是到网络视图的链接,但我不想要这样的链接.此外,文本将被翻译成其他语言,因此位置必须是动态的.
想要做到这一点:
我需要解决这个完全相同的问题:非常相似的文本,其中有这两个链接,跨越多行,并且需要它能够被翻译成任何语言(包括不同的词序,等等).我刚刚解决了这个问题,所以让我来分享一下我是如何做到的.
最初我想我应该创建属性文本,然后将点击的touch 位置映射到文本中的区域.虽然我认为这是可行的,但我也认为这是一种过于复杂的方法.
这就是我最终要做的:
SUMMARY:个
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");
}
}
希望这有帮助.我相信有很多更聪明、更优雅的方法可以做到这一点,但这正是我能想到的,而且效果很好.
以下是它在应用程序中的外观:
祝你好运!:-)
埃里克