在另一个活动中打开TextView链接,而不是默认浏览器

时间:2012-07-10 12:32:21

标签: android textview linkify

将text {autoLinkMask设置为Linkify.ALL后,我可以打开链接,浏览器会显示网页。

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

重要说明:

  • 更改textView内容不是一个选项,我需要将链接显示为他们所拥有的方案,
  • textView中有很多文字,而不仅仅是链接。

我浏览了movementMethodIntentFilters,可能会错过一些内容,但看起来无能为力。

那么,是否有任何选项拦截TextView中被触摸的链接,无法打开浏览器?

如果你想提及this SO问题,请提出一些论据,为什么它似乎没有解决与我相同的问题。

5 个答案:

答案 0 :(得分:24)

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

步骤2:运行所有URLSpan个对象的批量转换为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个对象。

答案 1 :(得分: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);
    
  5. 请注意,我在这里将所有类定义为静态,因此您可以直接将其放在Util类中,然后从任何地方轻松引用它。

答案 2 :(得分: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();

在库中,库使用自定义URLSpan实现替换TextView中的ClickableSpan,该实现将点击事件发送给用户提供的LinksHandler(s)。该机制与@commonsWare的解决方案非常相似。只需打包更高级别的API即可使其更易于使用。

答案 3 :(得分:0)

我认为David Hedlund's answer to himself是要走的路。在我的情况下,我有一个TextView包含用户收件箱的短信内容,我想处理以下行为:

  1. 如果找到了WEB URL,则将其链接并处理应用程序中的点击。
  2. 如果找到PHONE NUMBER,则将其链接并处理显示选择器的点击,让用户选择是否拨打该号码或将其添加到地址簿(所有应用内)
  3. 为实现这一点,我以这种方式使用了链接的答案:

    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及其中的数据。

答案 4 :(得分:-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);
            }
        });

onAreate of WebActivity Class:

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

在xml:

中的textview下添加
android:clickable="true"