10

I have a TextView in which I set HTML text. This text has many links. When you tap a link, it does not always trigger the onClick method. So, I am trying to expand the area of ClickableSpan, so that it is always responsive.

int start = strBuilder.getSpanStart(span);
int end = strBuilder.getSpanEnd(span);
int flags = strBuilder.getSpanFlags(span);
final ClickableSpan clickable = new ClickableSpan() {
  public void onClick(View view) {
    getTouchActions(span.getURL());
  }
};
strBuilder.setSpan(clickable, start, end, flags);
strBuilder.removeSpan(span);
Odysseas
  • 301
  • 2
  • 8
  • 1
    create a custom MovementMethod, extend this: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/text/method/LinkMovementMethod.java – pskink Oct 03 '14 at 13:56
  • Odys, do you mind sharing a snippet of your solution? – Rohan Dhruva Dec 18 '14 at 00:55

1 Answers1

8

The CustomMovementMethod has to extend ScrollingMovementMethod and override the onTouchEvent method. In order to add some extra space you have to define it in you dimensions and use that in the start/end span.

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

if (action == MotionEvent.ACTION_UP ||
    action == MotionEvent.ACTION_DOWN) {
  int x = (int) event.getX();
  int y = (int) event.getY();

  x -= widget.getTotalPaddingLeft();
  y -= widget.getTotalPaddingTop();

  x += widget.getScrollX();
  y += widget.getScrollY();

  Layout layout = widget.getLayout();
  int line = layout.getLineForVertical(y);
  int off = layout.getOffsetForHorizontal(line, x);

  int startSpan = off - context.getResources().getDimension(R.dimen.extra_space_start);
  int endSpan = off + context.getResources().getDimension(R.dimen.extra_space_end);

  ClickableSpan[] link = buffer.getSpans(startSpan, endSpan, 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);

}

You can call your custom link movement like this:

textView.setMovementMethod(new CustomLinkMovementMethod(context));
textView.setLinksClickable(true);
Odysseas
  • 301
  • 2
  • 8
  • 1
    This only increases clickable area horizontally (to left and right of the regular clickable space). Also, using dimensions like `extra_space_start` is misleading: getOffsetForHorizontal returns offset as a number of characters. Also, getSpans requires character indices, not dimensions. So this solution mixes dimensions with indices. – Singed Nov 14 '19 at 10:41