Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Format TextView to look like link

Tags:

android

I've been using the android:autoLink just fine for formatting links and such, but I need to use android:onClick so I can't use that in this case. The reasoning is that I find it too easy to click on a phone number accidentally, so I'm going to intercept the click with a confirmation Dialog and then call.

Is there an easy way to still make the phone number in my TextView look like a normal clickable link? I poked around the Android source code, but couldn't find any particular style for me to reference.

like image 916
telkins Avatar asked Aug 05 '12 22:08

telkins


People also ask

Can a TextView be clickable?

Just like Buttons and ImageViews we can add onClickListeners to TextViews by simply adding the attribute android:onClick="myMethod" to your TextView XML tag. The other way, TextView tv = (TextView) this.

How do I use Linkify?

To call linkify in android, we have to call linkify. addLinks(), in that method we have to pass textview and LinkifyMask. Linkify. WEB_URLS: It going make URL as web url, when user click on it, it going to send url to default web browsers.


Video Answer


3 Answers

This is the shortest solution:

final CharSequence text = tv.getText();
final SpannableString spannableString = new SpannableString( text );
spannableString.setSpan(new URLSpan(""), 0, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(spannableString, TextView.BufferType.SPANNABLE);

Sadly, the effect of clicking doesn't show up as being clicked on a real url link, but you can overcome it like so:

    final CharSequence text = tv.getText();
    final SpannableString notClickedString = new SpannableString(text);
    notClickedString.setSpan(new URLSpan(""), 0, notClickedString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    tv.setText(notClickedString, TextView.BufferType.SPANNABLE);
    final SpannableString clickedString = new SpannableString(notClickedString);
    clickedString.setSpan(new BackgroundColorSpan(Color.GRAY), 0, notClickedString.length(),
            Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    tv.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(final View v, final MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                tv.setText(clickedString);
                break;
            case MotionEvent.ACTION_UP:
                tv.setText(notClickedString, TextView.BufferType.SPANNABLE);
                v.performClick();
                break;
            case MotionEvent.ACTION_CANCEL:
                tv.setText(notClickedString, TextView.BufferType.SPANNABLE);
                break;
            }
            return true;
        }
    });

Another solution is to use Html.fromHtml(...) , where the text inside has links tags ("") .

If you wish for another solution, check this post.

like image 155
android developer Avatar answered Sep 20 '22 03:09

android developer


  • You can create a colors.xml resource file, what contains colors. Please take a look at Colors
  • If you want to underline your text, then please take a look at this post: Underline
  • Don't forget to add android:clickable="true" or setClickable(true) to your TextViews to make them clickable!
like image 26
Balázs Édes Avatar answered Sep 24 '22 03:09

Balázs Édes


Linkify is a great class, it hunts for complex patterns like URLs, phone numbers, etc and turns them into URLSpans. Rather than re-write the existing regular expressions I extended the URLSpan class and created a method to upgrade only the telephone URLSpans to a custom URLSpan with a confirmation dialog.

First my extended URLSpan class, ConfirmSpan:

class ConfirmSpan extends URLSpan {
    AlertDialog dialog;
    View mView;

    public ConfirmSpan(URLSpan span) {
        super(span.getURL());
    }

    @Override
    public void onClick(View widget) {
        mView = widget;

        if(dialog == null) {
            AlertDialog.Builder mBuilder = new AlertDialog.Builder(widget.getContext());
            mBuilder.setMessage("Do you want to call: " + getURL().substring(4) + "?");
            mBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            })
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    openURL();
                }
            });
            dialog = mBuilder.create();
        }
        dialog.show();
    }

    public void openURL() {
        super.onClick(mView);
    }
}

Next the method to swap out the different span classes:

private void swapSpans(TextView textView) {
    Spannable spannable = (Spannable) textView.getText();
    URLSpan[] spans = textView.getUrls();
    for(URLSpan span : spans) {
        if(span.getURL().toString().startsWith("tel:")) {
            spannable.setSpan(new ConfirmSpan(span), spannable.getSpanStart(span), spannable.getSpanEnd(span), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            spannable.removeSpan(span);
        }
    }
}

Finally all you need to do is create a TextView with the autoLink attribute:

android:autoLink="phone"

And remember to call the swapSpans() method. Understand that I wrote this for fun, there may be other methods of doing this but I am unaware of them at the moment. Hope this helps!

like image 34
Sam Avatar answered Sep 22 '22 03:09

Sam