在没有 html 的情况下在 UITextView 中打开点击的链接
Open tapped links in UITextView without html
我使用 Texture(以前的 AsyncDisplayKit)已经很长时间了,并且已经习惯了能够在 ASTextNode 中轻松地制作 phone 数字和可点击的链接。
然后我切换到一个旧的 xamarin 项目并在那里需要相同的功能。我一直在为这个问题寻找正确和简单的解决方案,发现人们建议使用 UIWebView 和类似的东西。
这有点棘手,所以我将尝试描述我在解决这个问题时想到的一些步骤。
- 尝试解析您的字符串以获得可能的链接。在我的例子中,字符串是
总是一组 phone 数字,例如 - “88002000600 +7999999999
8888800888" 所以这是一个简单的案例,但应该不是问题
通过正则表达式解析网站链接、电子邮件。
- 组成属性字符串并像这样分配必要的属性
--
//something right here and get your potential links list
var attributedContacts = new NSMutableAttributedString (value as string, UIFont.SystemFontOfSize (14), UIColor.White, UIColor.Clear);
foreach (var item in numbers) {
var nsStringItem = new NSString (item);
var nsTelPromptLink = new NSString (string.Format ("telprompt://{0}", item));
var range = attributedContacts.MutableString.LocalizedStandardRangeOfString (nsStringItem);
attributedContacts.AddAttribute (new NSString ("TextLinkAttributeName"), nsTelPromptLink, range);
}
textView.AttributedText = attributedContacts;
- 那么你应该在你的文本视图和句柄中添加一个手势识别器
按以下方式点击:
--
var tapRecognizer = new UITapGestureRecognizer ((UITapGestureRecognizer recognizer) => {
var textView = recognizer.View as UITextView;
if (textView == null)
return;
var tappedPoint = recognizer.LocationInView (textView);
tappedPoint.X -= textView.TextContainerInset.Left;
tappedPoint.Y -= textView.TextContainerInset.Top;
var layoutManager = textView.LayoutManager;
nfloat tmp = 0;
var tappedCharacterIndex = layoutManager.CharacterIndexForPoint (tappedPoint, textView.TextContainer, ref tmp);
NSRange range = new NSRange ();
var url = textView.AttributedText.GetAttribute ("TextLinkAttributeName", (nint)tappedCharacterIndex, out range) as NSString;
if (url == null)
return;
UIApplication.SharedApplication.OpenUrl (new NSUrl (url.ToString ()));
});
ContactsTextView.AddGestureRecognizer (tapRecognizer);
所以,这是一个相当粗略的解决方案,应该有额外的检查,但我认为这个想法本身很清楚。它可以轻松应用于 Swift 或 Objective-C.
中的原生解决方案
我使用 Texture(以前的 AsyncDisplayKit)已经很长时间了,并且已经习惯了能够在 ASTextNode 中轻松地制作 phone 数字和可点击的链接。
然后我切换到一个旧的 xamarin 项目并在那里需要相同的功能。我一直在为这个问题寻找正确和简单的解决方案,发现人们建议使用 UIWebView 和类似的东西。
这有点棘手,所以我将尝试描述我在解决这个问题时想到的一些步骤。
- 尝试解析您的字符串以获得可能的链接。在我的例子中,字符串是 总是一组 phone 数字,例如 - “88002000600 +7999999999 8888800888" 所以这是一个简单的案例,但应该不是问题 通过正则表达式解析网站链接、电子邮件。
- 组成属性字符串并像这样分配必要的属性
--
//something right here and get your potential links list
var attributedContacts = new NSMutableAttributedString (value as string, UIFont.SystemFontOfSize (14), UIColor.White, UIColor.Clear);
foreach (var item in numbers) {
var nsStringItem = new NSString (item);
var nsTelPromptLink = new NSString (string.Format ("telprompt://{0}", item));
var range = attributedContacts.MutableString.LocalizedStandardRangeOfString (nsStringItem);
attributedContacts.AddAttribute (new NSString ("TextLinkAttributeName"), nsTelPromptLink, range);
}
textView.AttributedText = attributedContacts;
- 那么你应该在你的文本视图和句柄中添加一个手势识别器 按以下方式点击:
--
var tapRecognizer = new UITapGestureRecognizer ((UITapGestureRecognizer recognizer) => {
var textView = recognizer.View as UITextView;
if (textView == null)
return;
var tappedPoint = recognizer.LocationInView (textView);
tappedPoint.X -= textView.TextContainerInset.Left;
tappedPoint.Y -= textView.TextContainerInset.Top;
var layoutManager = textView.LayoutManager;
nfloat tmp = 0;
var tappedCharacterIndex = layoutManager.CharacterIndexForPoint (tappedPoint, textView.TextContainer, ref tmp);
NSRange range = new NSRange ();
var url = textView.AttributedText.GetAttribute ("TextLinkAttributeName", (nint)tappedCharacterIndex, out range) as NSString;
if (url == null)
return;
UIApplication.SharedApplication.OpenUrl (new NSUrl (url.ToString ()));
});
ContactsTextView.AddGestureRecognizer (tapRecognizer);
所以,这是一个相当粗略的解决方案,应该有额外的检查,但我认为这个想法本身很清楚。它可以轻松应用于 Swift 或 Objective-C.
中的原生解决方案