2

The problem is to handle my own action on click on URL span. I wrote custom URLSpan but it doesn't work.

This is my custom URLSpan:

public class CustomURLSpan extends android.text.style.URLSpan {
    private Command mClickAction;

    public CustomURLSpan(String url, Command clickAction) {
        super(url);
        mClickAction = clickAction;
    }

    @Override
    public void onClick(View widget) {
        try {
            mClickAction.execute();
        } catch (Exception e) {
        }
    }

    public static void clickifyTextView(TextView tv, Command clickAction) {
        SpannableString current = new SpannableString(tv.getText());
        URLSpan[] spans =
                current.getSpans(0, current.length(), URLSpan.class);

        for (URLSpan span : spans) {
            int start = current.getSpanStart(span);
            int end = current.getSpanEnd(span);

            current.removeSpan(span);
            current.setSpan(new CustomURLSpan(span.getURL(), clickAction), start, end, 0);
        }
    }

    public interface Command {
        void execute();
    }
}

And here I use it:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

    Bundle bundle = getArguments();
    String message = bundle.getString("message");
    final Activity activity = getActivity();
    text = new TextView(activity);
    text.setText(message);

    Linkify.addLinks(text, Linkify.EMAIL_ADDRESSES);
    CustomURLSpan.clickifyTextView(text, new CustomURLSpan.Command() {
        @Override
        public void execute() {
            //I want to do my stuff here, but not working
        }
    });
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
    alertDialogBuilder.setView(text);
    alertDialogBuilder.setNegativeButton("Close", new DialogInterface.OnClickListener() {
        ...
}

But if I click on url, I get the native android dialog to choose email programm. All examples I find in internet are same.

EDIT: According to answer from @CommonWare. I just needed:

...
public static void clickifyTextView(TextView tv, Command clickAction) {
    SpannableString current = new SpannableString(tv.getText());
    URLSpan[] spans =
            current.getSpans(0, current.length(), URLSpan.class);

    for (URLSpan span : spans) {
        int start = current.getSpanStart(span);
        int end = current.getSpanEnd(span);

        current.removeSpan(span);
        current.setSpan(new CustomURLSpan(span.getURL(), clickAction), start, end, 0);
        tv.setText(current); //this is what I need
    }
}

public interface Command {
    void execute();
}
Vladimir Markeev
  • 654
  • 10
  • 25
Alexander Tumanin
  • 1,638
  • 2
  • 23
  • 37

2 Answers2

4

clickifyTextView() retrieves the text from the TextView, wraps it in a new SpannableString... then never updates the TextView. So clickifyTextView() is modifying a copy of what is in the TextView, which therefore does not affect the TextView.

Try calling setText() on the TextView after your span conversion loop in clickifyTextView().

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thank you for reply. I tried your solution. In this case I get the unclickable text, without any link at all. – Alexander Tumanin May 06 '15 at 23:21
  • 1
    @AlexanderTumanin: Make sure that you are calling `setText(current)`, not `setText(current.toString())`. If that is not it, check to see what sort of object you get back from `getText()`. If it implements `Spannable`, you do not need to create a new `SpannedString` and can just edit the contents of the `TextView` directly. – CommonsWare May 06 '15 at 23:34
  • Thank you! It works! I just was wrong setting text. I made it in my dialog, but I had to make it in CustomURLSpan. You save the huge of my time! – Alexander Tumanin May 06 '15 at 23:40
4

Set movementMethod = LinkMovementMethod() to your textview when using any ClickableSpan

Evgenii Vorobei
  • 1,457
  • 18
  • 20