Android TextView,Linkify 每种语言的美国电话号码
Posted
技术标签:
【中文标题】Android TextView,Linkify 每种语言的美国电话号码【英文标题】:Andorid TextView, Linkify US phone number in every language 【发布时间】:2018-06-13 03:57:08 【问题描述】:我有一条包含我们电话号码的短信。无论电话语言是什么,我都想让它们可点击。我调查了自动链接的工作原理,发现了我尝试在自定义 TextView 上使用的 Linkify.addLinks 方法。
public class PhoneNumberLinkTextView extends android.support.v7.widget.AppCompatTextView
public PhoneNumberLinkTextView(Context context)
super(context);
public PhoneNumberLinkTextView(Context context, @Nullable AttributeSet attrs)
super(context, attrs);
public PhoneNumberLinkTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
public void setUSNumberText(CharSequence text)
SpannableStringBuilder spanText = new SpannableStringBuilder(text);
if (addLinks(spanText))
setText(spanText);
else
setText(text);
public boolean addLinks(@NonNull SpannableStringBuilder text)
ArrayList<LinkSpec> links = new ArrayList<>();
gatherTelLinks(links, text);
if (links.isEmpty())
return false;
Object[] spans = text.getSpans(0, text.length(), Object.class);
final int count = spans.length;
for (int i = 0; i < count; i++)
text.removeSpan(spans[i]);
for (LinkSpec link: links)
applyLink(link.url, link.start, link.end, text);
return true;
private void gatherTelLinks(ArrayList<LinkSpec> links, Spannable s)
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
Iterable<PhoneNumberMatch> matches = phoneUtil.findNumbers(s.toString(),
Locale.US.getCountry(), PhoneNumberUtil.Leniency.POSSIBLE, Long.MAX_VALUE);
for (PhoneNumberMatch match : matches)
LinkSpec spec = new LinkSpec();
spec.url = "tel:" + normalizeNumber(match.rawString());
spec.start = match.start();
spec.end = match.end();
links.add(spec);
private void applyLink(String url, int start, int end, Spannable text)
URLSpan span = new URLSpan (url);
text.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
/**
* Normalize a phone number by removing the characters other than digits. If
* the given number has keypad letters, the letters will be converted to
* digits first.
*
* @param phoneNumber the number to be normalized.
* @return the normalized number.
*/
public String normalizeNumber(String phoneNumber)
if (TextUtils.isEmpty(phoneNumber))
return "";
StringBuilder sb = new StringBuilder();
int len = phoneNumber.length();
for (int i = 0; i < len; i++)
char c = phoneNumber.charAt(i);
// Character.digit() supports ASCII and Unicode digits (fullwidth, Arabic-Indic, etc.)
int digit = Character.digit(c, 10);
if (digit != -1)
sb.append(digit);
else if (sb.length() == 0 && c == '+')
sb.append(c);
else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
return normalizeNumber(PhoneNumberUtils.convertKeypadLettersToDigits(phoneNumber));
return sb.toString();
class LinkSpec
String url;
int start;
int end;
此代码目前在视觉上工作。我的美国号码的格式符合我的预期,但我的电话号码不可点击。
然后我尝试在我的 setText() 之后添加一个 setMovementMethod(LinkMovementMethod.getInstance()),但这次我丢失了格式化为电话号码的美国号码。
有谁知道我怎样才能实现我想要做的事情?
【问题讨论】:
【参考方案1】:我通过用扩展 ClickableSpan 的自定义类替换 URLSpan 来解决我的问题。
private class USNumberSpan extends ClickableSpan
private String url;
USNumberSpan(String url)
this.url = url;
@Override
public void onClick(View widget)
Uri uri = Uri.parse(url);
Context context = widget.getContext();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
try
context.startActivity(intent);
catch (ActivityNotFoundException e)
Log.w("URLSpan", "Activity was not found for intent, " + intent.toString(), e);
我不知道为什么这是有效的,而 URLSpan 不是,但我很高兴它有效。
【讨论】:
【参考方案2】:我在此链接上找到了一个 Kotlin 答案(由用户 Iliya Mashin 提供),其中包含适用于任何类型数字的模式:android:autoLink for phone numbers doesn't always work
我针对 Java 进行了调整,最后指定了至少 4 个数字(因此它不会链接一些以 3 个数字“xxxxx-xxx”结尾的邮政编码),所以,如果您不想要这个特定的限制,只需删除表达式末尾的“4,”)。
LinkifyCompat.addLinks(textView, Linkify.ALL); // This will use the usual linkify for any other format
Pattern pattern = Pattern.compile("([\\d|\\(][\\h|\\(\\d3\\)|\\.|\\-|\\d]4,\\d4,)", Pattern.CASE_INSENSITIVE);
LinkifyCompat.addLinks(textView, pattern, "tel://", null, null, null); // this adds the format for all kinds of phone number
如果您只想链接数字,请删除第一行(带有“Linkify.ALL”的行)。
【讨论】:
以上是关于Android TextView,Linkify 每种语言的美国电话号码的主要内容,如果未能解决你的问题,请参考以下文章
Android TextView 启用 LinkiFy 和 Href 标签
java 添加指向TextView的链接。 Linkify。字体:https://stackoverflow.com/questions/4746293/android-linkify-textvie