Tag Archives: linkify

Android里TextView中链接识别问题

假设你有一些文本内容,这些文本内容中可能会有一些URL。如果你希望用户在看这些文本内容的时候,同时可以方便的触发这些链接,该怎么做呢?

很多人会说,用Linkify, 简单的两句话就可以实现了:

textView.setText(content);
Linkify.addLinks(textView, Linkify.WEB_URLS);

但是Linkify除了可以指定识别链接的类型外,没有任何可以定制的内容。比如想单击链接打开浏览器,长按链接复制地址到剪贴板,就无法实现。

更重要的是,Linkify对链接的识别貌似非常粗糙,尤其是包含中文的内容。下面是Linkify识别结果的一个例子:

Screenshot_20160514-143339

尝试找各种解决方案,最后觉得Android-TextView-LinkBuilder是最好的一个方案。

contentView.setText(content);
LinkBuilder.on(contentView).addLinks(getPostSupportedLinks()).build();
    public static void openLink(String link, Activity activity) {
        Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
        try {
            activity.startActivity(browserIntent);
        } catch(ActivityNotFoundException e) {
            Toast.makeText(activity, "链接打开错误:" + e.toString(), Toast.LENGTH_LONG).show();
        }
    }

    public static void sendEmail(String link, Activity activity) {
        /* Create the Intent */
        final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);

        /* Fill it with Data */
        emailIntent.setType("plain/text");
        emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{link});
        emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
        emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, " \n \n \n \n--\n来自zSMTH的邮件\n");

        try {
            activity.startActivity(Intent.createChooser(emailIntent, "发邮件..."));
        } catch(ActivityNotFoundException e) {
            Toast.makeText(activity, "链接打开错误:" + e.toString(), Toast.LENGTH_LONG).show();
        }
    }

    // this will be called in PostRecyclerViewAdapter & MailContentActivity
    public static List<Link> getPostSupportedLinks(final Activity activity) {
        List<Link> links = new ArrayList<>();

        // web URL link
        Link weburl = new Link(Regex.WEB_URL_PATTERN);
        weburl.setTextColor(Color.parseColor("#00BCD4"));
        weburl.setHighlightAlpha(.4f);
        weburl.setOnClickListener(new Link.OnClickListener() {
            @Override
            public void onClick(String clickedText) {
                ActivityUtils.openLink(clickedText, activity);
            }
        });
        weburl.setOnLongClickListener(new Link.OnLongClickListener() {
            @Override
            public void onLongClick(String clickedText) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                    final android.content.ClipboardManager clipboardManager = (android.content.ClipboardManager)
                            activity.getSystemService(Context.CLIPBOARD_SERVICE);
                    final android.content.ClipData clipData = android.content.ClipData.newPlainText("PostContent", clickedText);
                    clipboardManager.setPrimaryClip(clipData);
                } else {
                    final android.text.ClipboardManager clipboardManager = (android.text.ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE);
                    clipboardManager.setText(clickedText);
                }
                Toast.makeText(SMTHApplication.getAppContext(), "链接已复制到剪贴板", Toast.LENGTH_SHORT).show();
            }
        });

        // email link
        Link emaillink = new Link(Regex.EMAIL_ADDRESS_PATTERN);
        emaillink.setTextColor(Color.parseColor("#00BCD4"));
        emaillink.setHighlightAlpha(.4f);
        emaillink.setOnClickListener(new Link.OnClickListener() {
            @Override
            public void onClick(String clickedText) {
                ActivityUtils.sendEmail(clickedText, activity);
            }
        });

        links.add(weburl);
        links.add(emaillink);

        return links;
    }

这样就可以完全由自己去控制需要识别的内容,然后对单击、长按动作采用合适的操作了。

https://github.com/klinker24/Android-TextView-LinkBuilder