Adding OnTouch and OnClickListener to the links in a TextView and changing background color of the link

715 views Asked by At

I have a textview and links in it. I want the links highlighted when I touch them and also I want to open a Alertdialog when I longclick them. I tried to reach the solution by customizing URLSpan, but, since I can't access to mView before OnClick is called, I can't set the listeners:

class ConfirmSpan extends URLSpan{
    View mView;
    URLSpan span;

    public ConfirmSpan(URLSpan span) {
        super(span.getURL());
        this.span = span;

      //there is a nullpointerexception here since mView is null now.
        mView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                ((TextView)v).setBackgroundColor(0xcccccccc);
                return false;
            }
        });

      //this is also an exception
        mView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {

                Log.d("INFO","long click yay!");
                return false;
            }
        });
    }

  //this should be called to reach the view. But then I can't handle touch state.
    @Override
    public void onClick(View widget) {
        mView = widget;

        //bla bla..
    }

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

}

I think I must customize LinkMovementMethod class but how? Any comment will be appreciated. UPDATE: I am now able to handle touch event with this code:

public class CustomLinkMovementMethod extends LinkMovementMethod {
private static CustomLinkMovementMethod sInstance;

@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
    // Here I am changing backgorund color
    if(event.getAction() == MotionEvent.ACTION_DOWN)
        widget.setBackgroundColor(0xcccccccc);
    if(event.getAction() == MotionEvent.ACTION_UP)
        widget.setBackgroundColor(0xffffffff);
    return super.onTouchEvent(widget, buffer, event);
}
public static MovementMethod getInstance() {
    if (sInstance == null)
        sInstance = new CustomLinkMovementMethod();

    return sInstance;
}

}

But TextView named widget, a parameter OnTouchEvent(), is not what I want. It is all of the text. So, when I touch the link, text becomes gray altogether. I think I need some other methods like coloring background of the link by finding coordinates of the start and end lines of the link.

1

There are 1 answers

0
qtyq On BEST ANSWER

Thank you for asking this question, I think I may have a solution for you.

Check out the code in https://gist.github.com/qtyq/90f9b4894069a8b3676c

It is a factory helper class for a SpannableString which allows you to easily create a SpannableString by:

  1. passing the original String into the static init(String s) method
  2. calling the makeLink(...) method to make the substring you want into a link
  3. optionally calling other methods like makeBold(...) (which is already called in makeLink) or setColor(...) to customise the look
  4. and finally calling create() to create the SpannableString object, which you can just apply to your textView with setText(...).

Here's an example of its usage:

SpannableString ss = SpannableBuilder.init(bottomText)
        .setColor("Terms & Conditions", getResources().getColor(R.color.orange))
        .makeLink(getContext(), "Terms & Conditions", terms)
        .setColor("Privacy Policy", getResources().getColor(R.color.orange))
        .makeLink(getContext(), "Privacy Policy", policy)
        .create();
textView1.setText(ss);

And of course you can customise the methods already in that class or add your own ones if you need further customisation, just have a read of Google's documentation for SpannableString for more information on what you can do.