简体   繁体   中英

Create a TextView link in Android

I've the following convenience method:

public static void createLink(TextView textView, String linkText, String linkHRef) {    
    String htmlLink = "<a href='%s'>%s</a>";
    Spanned spanned = Html.fromHtml(String.format(htmlLink, linkHRef, linkText));
    textView.setMovementMethod(LinkMovementMethod.getInstance());
    textView.setHighlightColor(ContextCompat.getColor(textView.getContext(), android.R.color.holo_green_light));
    textView.setText(spanned, TextView.BufferType.SPANNABLE);
}

I'm using that method to create a clickable link inside a textview, given the textview itself, the text link and the url.

Now I would to show a "click effect" when the user tap on that text.

How can I achieve this?

Thank you very much!


UPDATE

I was able to obtain what I mean in this way:

public static void createLink(TextView textView, String linkText, String linkHRef, @ColorRes int linkColorStateList) {
    String htmlLink = "<a href='%s'>%s</a>";
    Spanned spanned = Html.fromHtml(String.format(htmlLink, linkHRef, linkText));
    textView.setTextColor(ContextCompat.getColorStateList(textView.getContext(), linkColorStateList));
    textView.setMovementMethod(LinkMovementMethod.getInstance());
    textView.setText(spanned, TextView.BufferType.SPANNABLE);
}

And defining a color state list xml file:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_focused="true" android:state_pressed="false" android:color="@color/green" />
   <item android:state_focused="true" android:state_pressed="true" android:color="@color/green_dark" />
   <item android:state_focused="false" android:state_pressed="true" android:color="@color/green_dark" />
   <item android:color="@color/green" />
</selector>

Now the color of the text contained in the TextView changes when I press on it.

The only things that I don't understand is why the TextView background color changes too, becoming bright blue. My code doesn't do that, I think. Anyone maybe knows that?

只需将android:autoLink="web"到TextView内的.xml文件中

protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
                         String description = "Your Description http://stackoverflow.com/";

                         Spannable spannable = new SpannableString( description );
                         Linkify.addLinks(spannable, Linkify.WEB_URLS);
                         URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
                         for (URLSpan urlSpan : spans) {
                            LinkSpan linkSpan = new LinkSpan(urlSpan.getURL());
                            int spanStart = spannable.getSpanStart(urlSpan);
                            int spanEnd = spannable.getSpanEnd(urlSpan);
                            spannable.setSpan(linkSpan, spanStart, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            spannable.removeSpan(urlSpan);
                        }

                 txt_textview.setMovementMethod(EnhancedLinkMovementMethod.getInstance());
                 txt_textview.setText(spannable, BufferType.SPANNABLE);

        }
    //if you want to open in app web

         private class LinkSpan extends URLSpan {
                    private LinkSpan(String url) {
                        super(url);
                    }

                    @Override
                    public void onClick(View view) {
                        String url = getURL();
                        //Toast.makeText(getApplicationContext(), ""+url, Toast.LENGTH_SHORT).show();
                        Intent webIntent = new Intent(this,Web.class);
                        webIntent.putExtra("url", url);
                        startActivity(webIntent);
                    }
                }



    public class EnhancedLinkMovementMethod extends ArrowKeyMovementMethod {

        private static EnhancedLinkMovementMethod sInstance;

        private static Rect sLineBounds = new Rect();

        public static MovementMethod getInstance() {
            if (sInstance == null) {
                sInstance = new EnhancedLinkMovementMethod();
            }
            return sInstance;
        }

        @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
            int action = event.getAction();

            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {

                int index = getCharIndexAt(widget, event);
                if (index != -1) {
                    ClickableSpan[] link = buffer.getSpans(index, index, ClickableSpan.class);
                    if (link.length != 0) {
                        if (action == MotionEvent.ACTION_UP) {
                            link[0].onClick(widget);
                        }
                        else if (action == MotionEvent.ACTION_DOWN) {
                            Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]));
                        }
                        return true;
                    }
                }
                /*else {
                    Selection.removeSelection(buffer);
                }*/

            }

            return super.onTouchEvent(widget, buffer, event);
        }

        private int getCharIndexAt(TextView textView, MotionEvent event) {
            // get coordinates
            int x = (int) event.getX();
            int y = (int) event.getY();
            x -= textView.getTotalPaddingLeft();
            y -= textView.getTotalPaddingTop();
            x += textView.getScrollX();
            y += textView.getScrollY();

            /*
             * Fail-fast check of the line bound.
             * If we're not within the line bound no character was touched
             */
            Layout layout = textView.getLayout();
            int line = layout.getLineForVertical(y);
            synchronized (sLineBounds) {
                layout.getLineBounds(line, sLineBounds);
                if (! sLineBounds.contains(x, y)) {
                    return -1;
                }
            }

            // retrieve line text
            Spanned text = (Spanned) textView.getText();
            int lineStart = layout.getLineStart(line);
            int lineEnd = layout.getLineEnd(line);
            int lineLength = lineEnd - lineStart;
            if (lineLength == 0) {
                return -1;
            }
            Spanned lineText = (Spanned) text.subSequence(lineStart, lineEnd);

            // compute leading margin and subtract it from the x coordinate
            int margin = 0;
            LeadingMarginSpan[] marginSpans = lineText.getSpans(0, lineLength, LeadingMarginSpan.class);
            if (marginSpans != null) {
                for (LeadingMarginSpan span : marginSpans) {
                    margin += span.getLeadingMargin(true);
                }
            }
            x -= margin;

            // retrieve text widths
            float[] widths = new float[lineLength];
            TextPaint paint = textView.getPaint();
            paint.getTextWidths(lineText, 0, lineLength, widths);

            // scale text widths by relative font size (absolute size / default size)
            final float defaultSize = textView.getTextSize();
            float scaleFactor = 1f;
            AbsoluteSizeSpan[] absSpans = lineText.getSpans(0, lineLength, AbsoluteSizeSpan.class);
            if (absSpans != null) {
                for (AbsoluteSizeSpan span : absSpans) {
                    int spanStart = lineText.getSpanStart(span);
                    int spanEnd = lineText.getSpanEnd(span);
                    scaleFactor = span.getSize() / defaultSize;
                    int start = Math.max(lineStart, spanStart);
                    int end = Math.min(lineEnd, spanEnd);
                    for (int i = start; i < end; i++) {
                        widths[i] *= scaleFactor;
                    }
                }
            }

            // find index of touched character
            float startChar = 0;
            float endChar = 0;
            for (int i = 0; i < lineLength; i++) {
                startChar = endChar;
                endChar += widths[i];
                if (endChar >= x) {
                    // which "end" is closer to x, the start or the end of the character?
                    int index = lineStart + (x - startChar < endChar - x ? i : i + 1);
                    //Logger.e(Logger.LOG_TAG, "Found character: " + (text.length()>index ? text.charAt(index) : ""));
                    return index;
                }
            }

            return -1;
        }
    }

TextView textView = (TextView) view.findViewById(R.id.textview); SpannableString linkText= new SpannableString("linkText"); linkText.setSpan(new UnderlineSpan(), 0, linkText.length(), 0); textView.setText(linkText);

This above code will make your textview have underline like link . Now Using implicit intent.

Intent i= new Intent(this,Intent.ACTION_VIEW); i.setData(Uri.parse("your http url"));

startActivity(i);

try this :

textView.setOnClickListener(new Button.OnClickListener() {  
        public void onClick(View v)
            {
                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(textView.getText().toString()));
                startActivity(browserIntent);
            }
         });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM