18

将 textViewautoLinkMask设置为Linkify.ALL,我可以打开链接并且浏览器显示网页。

我需要调用另一个活动来完成它的 webView 而不离开应用程序。

重要笔记:

  • 更改 textView 内容不是一种选择,我需要将链接与它们所拥有的方案一样显示,
  • textView 中有很多文本,不仅仅是链接。

我看了看movementMethodIntentFilters可能会错过一些东西,但看起来无济于事。

那么,是否有任何选项可以拦截中的触摸链接以在TextView不打开浏览器的情况下对其进行操作?

如果您想提及这个SO 问题,请给出一些论据,为什么它似乎无法解决与我相同的问题。

4

5 回答 5

26

步骤#1:创建您自己的子类,ClickableSpan在其方法中执行您想要的操作onClick()(例如,调用YourCustomClickableSpan

URLSpan步骤#2:将所有对象批量转换为YourCustomClickableSpan对象。我有一个实用程序类:

public class RichTextUtils {
    public static <A extends CharacterStyle, B extends CharacterStyle> Spannable replaceAll(Spanned original,
    Class<A> sourceType,
    SpanConverter<A, B> converter) {
        SpannableString result=new SpannableString(original);
        A[] spans=result.getSpans(0, result.length(), sourceType);

        for (A span : spans) {
            int start=result.getSpanStart(span);
            int end=result.getSpanEnd(span);
            int flags=result.getSpanFlags(span);

            result.removeSpan(span);
            result.setSpan(converter.convert(span), start, end, flags);
        }

        return(result);
    }

    public interface SpanConverter<A extends CharacterStyle, B extends CharacterStyle> {
        B convert(A span);
    }
}

你会像这样使用它:

yourTextView.setText(RichTextUtils.replaceAll((Spanned)yourTextView.getText(),
                                             URLSpan.class,
                                             new URLSpanConverter()));

有这样的习惯URLSpanConverter

class URLSpanConverter
      implements
      RichTextUtils.SpanConverter<URLSpan, YourCustomClickableSpan> {
    @Override
    public URLSpan convert(URLSpan span) {
      return(new YourCustomClickableSpan(span.getURL()));
    }
  }

将所有URLSpan对象转换为YourCustomClickableSpan对象。

于 2012-07-10T16:12:27.407 回答
3

我通过添加 Click Listener 使 @CommonsWare 的代码更加优雅和清晰,它可以直接添加到替换 URL Spans 的相同方法中。

  1. 定义YourCustomClickableSpan Class.

     public static class YourCustomClickableSpan extends ClickableSpan {
    
        private String url;
        private OnClickListener mListener;
    
        public YourCustomClickableSpan(String url, OnClickListener mListener) {
            this.url = url;
            this.mListener = mListener;
        }
    
        @Override
        public void onClick(View widget) {
            if (mListener != null) mListener.onClick(url);
        }
    
        public interface OnClickListener {
            void onClick(String url);
        }
    }
    
  2. 定义RichTextUtils Class哪个将操作 TextView 的跨区文本。

    public static class RichTextUtils {
    
        public static <A extends CharacterStyle, B extends CharacterStyle> Spannable replaceAll (
              Spanned original,
              Class<A> sourceType,
              SpanConverter<A, B> converter,
              final ClickSpan.OnClickListener listener) {
    
                  SpannableString result = new SpannableString(original);
                  A[] spans = result.getSpans(0, result.length(), sourceType);
    
                  for (A span : spans) {
                      int start = result.getSpanStart(span);
                      int end = result.getSpanEnd(span);
                      int flags = result.getSpanFlags(span);
    
                      result.removeSpan(span);
                      result.setSpan(converter.convert(span, listener), start, end, flags);
                  }
    
                  return (result);
              }
    
              public interface SpanConverter<A extends CharacterStyle, B extends CharacterStyle> {
                  B convert(A span, ClickSpan.OnClickListener listener);
    
         }
    }
    
  3. 定义URLSpanConverter class哪个将使用您的自定义跨度执行替换 URLSpan 的实际代码。

        public static class URLSpanConverter
            implements RichTextUtils.SpanConverter<URLSpan, ClickSpan> {
    
    
            @Override
            public ClickSpan convert(URLSpan span, ClickSpan.OnClickListener listener) {
                return (new ClickSpan(span.getURL(), listener));
            }
       }
    
  4. 用法

    TextView textView = ((TextView) this.findViewById(R.id.your_id));
    textView.setText("your_text");
    Linkify.addLinks(contentView, Linkify.ALL);
    
    Spannable formattedContent = UIUtils.RichTextUtils.replaceAll((Spanned)textView.getText(), URLSpan.class, new UIUtils.URLSpanConverter(), new UIUtils.ClickSpan.OnClickListener() {
    
        @Override
        public void onClick(String url) {
            // Call here your Activity
        }
    });
    textView.setText(formattedContent);
    

请注意,我在这里将所有类都定义为静态的,因此您可以将其直接放在您的 Util 类中,然后从任何地方轻松引用它。

于 2015-01-31T15:05:27.553 回答
2

只是为了分享一个使用我刚刚创建的Textoo的替代解决方案:

    TextView yourTextView = Textoo
        .config((TextView) findViewById(R.id.your_text_view))
        .addLinksHandler(new LinksHandler() {
            @Override
            public boolean onClick(View view, String url) {
                if (showInMyWebView(url)) {
                    //
                    // Your custom handling here
                    //
                    return true;  // event handled
                } else {
                    return false; // continue default processing i.e. launch browser app to display link
                }
            }
        })
        .apply();

在引擎盖下,库将URLSpanTextView 中的 's 替换为自定义ClickableSpan实现,该实现将点击事件分派给用户提供LinksHandler的(s)。该机制与@commonsWare 的解决方案非常相似。只需打包在更高级别的 API 中,使其更易于使用。

于 2016-01-14T08:36:11.957 回答
0

我认为David Hedlund 对自己的回答是要走的路。在我的情况下,我有一个包含 SMS 内容表单用户收件箱的 TextView,我想处理休闲行为:

  1. 如果找到 WEB URL,则链接它并处理应用程序中的点击。
  2. 如果找到 PHONE NUMBER,则将其链接并处理显示选择器的点击,让用户选择是拨打该号码还是将其添加到地址簿(都在应用程序中)

为此,我以这种方式使用了链接的答案:

TextView tvBody = (TextView)findViewById(R.id.tvBody);
tvBody.setText(messageContentString);

// now linkify it with patterns and scheme
Linkify.addLinks(tvBody, Patterns.WEB_URL, "com.my.package.web:");
Linkify.addLinks(tvBody, Patterns.PHONE, "com.my.package.tel:");

现在在清单中:

<activity
    android:name=".WebViewActivity"
    android:label="@string/web_view_activity_label">
    <intent-filter>
        <category android:name="android.intent.category.DEFAULT" />
        <action android:name="android.intent.action.VIEW"/>
        <data android:scheme="com.duckma.phonotto.web"/>
    </intent-filter>
</activity>
...
<activity
    android:name=".DialerActivity"
    android:label="@string/dialer_activity_label">
    <intent-filter>
        <category android:name="android.intent.category.DEFAULT" />
        <action android:name="android.intent.action.VIEW"/>
        <data android:scheme="com.duckma.phonotto.tel"/>
    </intent-filter>
</activity>
<activity
    android:name=".AddressBook"
    android:label="@string/address_book_activity_label">
    <intent-filter>
        <category android:name="android.intent.category.DEFAULT" />
        <action android:name="android.intent.action.VIEW"/>
        <data android:scheme="com.duckma.phonotto.tel"/>
    </intent-filter>
</activity>

它对我来说很好用,当用户单击电话号码时,选择器将显示拨号器/地址簿选项。在被调用的活动getIntent().getData()中,用于查找传递的带有数据的 Url。

于 2015-02-23T12:41:38.770 回答
-3

比这样做:

        TextView textView=(TextView) findViewById(R.id.link);
        textView.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                Intent intent=new Intent(YourActivityName.this,WebActivity.class);
                startActivity(intent);
            }
        });

WebActivity 类的 onCreate:

WebView webView=(WebView) findViewById(R.id.web);
webView.loadUrl("http://www.google.co.in");

在 xml 中的 textview 下添加:

android:clickable="true"
于 2012-07-10T13:22:24.990 回答