TextView的富文本带来了很多便利,但也带了不少坑,本篇主要解决设置了ClickableSpan、OnClickListener、OnLongClickListener带来的问题。
我们先来看ClickableSpan、OnClickListener的坑,我们会发现,我们点击的是Span部分,ClickableSpan的onClick会被执行,但OnClickListener也会执行onClick方法,是不是很刺激啊,其实最好的办法是在ClickableSpan的onClick被执行时,不要执行OnClickListener 的onClick方法就行了(哈哈,那不是废话吗)
所以,我们自定义OnTouchListener监听TextView的事件,来拦截Touch自行处理行为:
public class CustomTextViewTouchListener implements View.OnTouchListener {
private View.OnClickListener mOnClickListener;
public CustomTextViewTouchListener(View.OnClickListener onClickListener) {
mOnClickListener = onClickListener;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
TextView tv = (TextView) v;
CharSequence text = tv.getText();
if (action == MotionEvent.ACTION_UP) {
if (text instanceof Spanned) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= tv.getTotalPaddingLeft();
y -= tv.getTotalPaddingTop();
x += tv.getScrollX();
y += tv.getScrollY();
Layout layout = tv.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = ((Spanned) text).getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
link[0].onClick(tv);
} else {
//do textview click event
if (null != mOnClickListener) {
mOnClickListener.onClick(v);
}
}
} else {
if (null != mOnClickListener) {
mOnClickListener.onClick(v);
}
}
}
return true;
}
}
这样我们就解决了ClickableSpan、OnClickListener会一起执行的问题,但是这样的话,我们给TextView设置了长按事件OnLongClickListener就没办法工作了,所以我们还需在原来的代码上做个修改,如下:
public class IMCustomTouchListener implements View.OnTouchListener {
private long mLastActionDownTime = -1;
private View mView;
private Handler mHandler = new Handler(Looper.getMainLooper());
private Runnable mLongClickRunnable = new Runnable() {
@Override
public void run() {
if (mView != null) {
mView.performLongClick();
}
}
};
private void removeLongClickRunnable() {
mHandler.removeCallbacksAndMessages(null);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
TextView tv = (TextView) v;
CharSequence text = tv.getText();
if (action != MotionEvent.ACTION_MOVE) {
removeLongClickRunnable();
}
if (action == MotionEvent.ACTION_DOWN) {
mLastActionDownTime = System.currentTimeMillis();
this.mView = v;
mHandler.postDelayed(mLongClickRunnable, ViewConfiguration.getLongPressTimeout());
} else {
long actionUpTime = System.currentTimeMillis();
if (actionUpTime - mLastActionDownTime >= ViewConfiguration.getLongPressTimeout()) {
//v.performLongClick();
return true;
}
if (action == MotionEvent.ACTION_UP) {
if (text instanceof Spanned) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= tv.getTotalPaddingLeft();
y -= tv.getTotalPaddingTop();
x += tv.getScrollX();
y += tv.getScrollY();
Layout layout = tv.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = ((Spanned) text).getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
link[0].onClick(tv);
} else {
//do textview click event
v.performClick();
}
} else {
v.performClick();
}
}
}
return true;
}
}
完美解决…