I wanted to use some URLSpan inside a textView, so I've used something like:
final Spanned spanned=Html.fromHtml(getString(R.string.test));
msgTextView.setText(spanned);
It works, but when clicking an item, it stays clicked. it's as if I still touch the link...
I've tried to clear the focus from the textView and to set the focus on another view, but none of those helped.
I've also tried to remove the UrlSpan and add a new one instead, each time it gets clicked, but it didn't work. Here's the code:
public static Spannable setOnLinkClickedListener(final Spanned original,final IOnLinkClickListener listener)
{
final SpannableString result=new SpannableString(original);
final URLSpan[] spans=result.getSpans(0,result.length(),URLSpan.class);
for(final URLSpan span : spans)
{
final int start=result.getSpanStart(span);
final int end=result.getSpanEnd(span);
final int flags=result.getSpanFlags(span);
result.removeSpan(span);
final String url=span.getURL();
result.setSpan(new CustomURLSpan(url,start,result,end,listener,flags),start,end,flags);
}
return result;
}
private static final class CustomURLSpan extends URLSpan
{
private final int _start;
private final SpannableString _result;
private final String _url;
private final int _end;
private final IOnLinkClickListener _listener;
private final int _flags;
private CustomURLSpan(final String url,final int start,final SpannableString result,final int end,final IOnLinkClickListener listener,final int flags)
{
super(url);
_start=start;
_result=result;
_url=url;
_end=end;
_listener=listener;
_flags=flags;
}
@Override
public void onClick(final View widget)
{
if(_listener==null||!_listener.onClick(widget,_url))
super.onClick(widget);
_result.removeSpan(this);
_result.setSpan(new CustomURLSpan(_url,_start,_result,_end,_listener,_flags),_start,_end,_flags);
}
}
How do I clear the selection/clicking effect that stays on URLSpan each time it gets clicked?
I had the same issue before. Its probably because of android:textIsSelectable attribute of the textView you are using. Remove it or set it false and it will be solved.
Subclass LinkMovementMethod
and override onTouchEvent
to call Selection.removeSelection(buffer);
after link[0].onClick(widget);
.
// 1. Subclass LinkMovementMethod.
public class CustomLinkMovementMethod extends LinkMovementMethod {
// 2. Copy this method from LinkMovementMethod.
@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);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
Selection.removeSelection(buffer); // 3. Add this line.
} 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);
}
}
BTW, if you use it in ListView
, subclass TextView
and override setPressed
to call invalidate();
, because ListView
defers calling setPressed
.
public class CustomTextView extends TextView {
public CustomTextView(Context context) {
super(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
invalidate();
}
}
this answer is work for me. I test in API19 API26 with Checkbox
, CheckedTexView
TextView
all clarify
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.