Open TextView links at another activity, not default browser

后端 未结 5 731
忘掉有多难
忘掉有多难 2020-12-13 04:52

Having the textView with autoLinkMask set to Linkify.ALL, i\'m able to open the links and the browser shows the web-page.

I need to call a

相关标签:
5条回答
  • 2020-12-13 05:30

    Step #1: Create your own subclass of ClickableSpan that does what you want in its onClick() method (e.g., called YourCustomClickableSpan)

    Step #2: Run a bulk conversion of all of the URLSpan objects to be YourCustomClickableSpan objects. I have a utility class for this:

    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);
        }
    }
    

    You would use it like this:

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

    with a custom URLSpanConverter like this:

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

    to convert all URLSpan objects to YourCustomClickableSpan objects.

    0 讨论(0)
  • 2020-12-13 05:30

    I make @CommonsWare's code more elegant and clear by adding Click Listener which can be added directly into the same method which replace URL Spans.

    1. Define 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. Define RichTextUtils Class which will manipulate the Spanned text of your 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. Define URLSpanConverter class which will do the actual code of replacement URLSpan with Your Custom Span.

          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. Usage

      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);
      

    Note that I defined all classes here as static so you can put it directly info your Util class and then reference it easily from any place.

    0 讨论(0)
  • 2020-12-13 05:35

    Just to share an alternative solution using Textoo that I just created:

        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();
    

    Under the hood the library replace URLSpan's in the TextView with custom ClickableSpan implementation that dispatch click events to the user supplied LinksHandler(s). The mechanism is very similar to solution from @commonsWare. Just package in a higher level API to make it easier to use.

    0 讨论(0)
  • 2020-12-13 05:38

    Than do this:

            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);
                }
            });
    

    onCreate of WebActivity Class:

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

    Add this under textview in xml:

    android:clickable="true"
    
    0 讨论(0)
  • 2020-12-13 05:45

    I think David Hedlund's answer to himself is the way to go. In my case I had a TextView containing SMS content form user's inbox and I wanted to handle the fallowing behaviour:

    1. If a WEB URL is found then linkify it and handle the click within the application.
    2. If PHONE NUMBER is found, then linkify it and handle the click showing a picker to let the user choose if call the number or add it to the address-book (all within the application)

    To achieve this I used the linked answer in this way:

    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:");
    

    Now in the manifest:

    <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>
    

    And it works just fine for me, when user clicks a phone number the picker will show up with the dialer/address book choice. In the called activities use getIntent().getData() to find the passed Url with the data in it.

    0 讨论(0)
提交回复
热议问题