这几天在开发一个图片混排带有超链的列表的时候,发现如果带有可点击的超链的textview以后,ellsize属性,即以省略号结尾的属性就不生效了,结果造成列表混乱,然后经过排查,刚开始以为是带图片的问题,后来发现并不是,而是下面这行代码的问题,只要设置这行代码就混乱了。
holder.connectInfo.setMovementMethod(LinkMovementMethod.getInstance());//不设置 没有点击事件
在查阅各种资料以后,发现这个问题的博客很少,现有的博客很多还是有点问题,不能根治,例如这个试着去重写textview,结果还是未果https://www.zhihu.com/question/52436308/answer/130588361
,然后没办法,就试着去看
LinkMovementMethod的源码,然后发现
- if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
- && mText instanceof Spannable && mLayout != null) {
- boolean handled = false;
- if (mMovement != null) {
- handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
- }
- final boolean textIsSelectable = isTextSelectable();
- if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) {
- // The LinkMovementMethod which should handle taps on links has not been installed
- // on non editable text that support text selection.
- // We reproduce its behavior here to open links for these.
- ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(),
- getSelectionEnd(), ClickableSpan.class);
- if (links.length > 0) {
- links[0].onClick(this);
- handled = true;
- }
- }
它里面的部分就是通过setMovementMethod方法设置的对象。由于我们设置的是LinkMovementMethod的一个实例,继续打开LinkMovementMethod源码查看其中onTouchEvent的代码。
- if (mMovement != null) {
- handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
- }
然后我试着将它的重要代码抽取出来,下面的代码代替它的
setMovementMethod方法,就可以了,完美解决混乱问题。
//因为setMovementMethod会导致ellsize方法失效,图文混排错乱,所以这种方法保持正常
holder.connectInfo.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
TextView tv = (TextView) v;
CharSequence text = tv.getText();
if (text instanceof SpannedString) {
if (action == MotionEvent.ACTION_UP) {
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 = ((SpannedString)text).getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
link[0].onClick(tv);
} else {
}
}
}
return true;
}
});
下面还是上一下完整的代码吧,不然有的童鞋还是不理解
/**
* 设置超链
*/
private void setSuperLinkContent(final ViewHolder holder, final String content, final Dynamic dynamicInfo) {
String contents = "<font>" + content + "</font><img src='icon_link'> 查看详情";
Html.ImageGetter imageGetter = new Html.ImageGetter() {
@Override
public Drawable getDrawable(String source) {
if (source.endsWith("icon_link")) {
Drawable drawable = mContext.getResources().getDrawable(R.drawable.icon_link);
int fontH = (int) (mContext.getResources().getDimension(
R.dimen.publish_consult_hint) * 1.2);
int height = fontH;
int width = (int) ((float) drawable.getIntrinsicWidth() / (float) drawable
.getIntrinsicHeight()) * fontH;
if (width == 0) {
width = drawable.getIntrinsicWidth();
}
drawable.setBounds(0, 0, width, height);
return drawable;
}
return null;
}
};
//底部提示语 快速咨询为超链
SpannableString str = new SpannableString(Html.fromHtml(contents, imageGetter, null));
str.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds); //设置文本的颜色
ds.setColor(Color.parseColor("#2e84c6"));
//超链接形式的下划线,false 表示不显示下划线,true表示显示下划线
ds.setUnderlineText(false);
}
@Override
public void onClick(View widget) {
if (!TextUtils.isEmpty(dynamicInfo.getLinkUrl())) {
WebViewActivity.invoke(mContext, dynamicInfo.getLinkUrl());
}
}
}, content.length(), content.length() + 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.connectInfo.setText(str);
// holder.connectInfo.setMovementMethod(LinkMovementMethod.getInstance());//不设置 没有点击事件
holder.connectInfo.setHighlightColor(Color.TRANSPARENT); //设置点击后的颜色为透明
//因为setMovementMethod会导致ellsize方法失效,图文混排错乱,所以这种方法保持正常
holder.connectInfo.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
TextView tv = (TextView) v;
CharSequence text = tv.getText();
if (text instanceof SpannedString) {
if (action == MotionEvent.ACTION_UP) {
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 = ((SpannedString)text).getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
link[0].onClick(tv);
} else {
}
}
}
return true;
}
});
}
这样就可以了 下面是效果 ps:他们是一个列表,由于着急把这个记录下来还有后面的工作呢,就没录视频,这个超链也是正常可以点击的,列表后面限制的 ...也是正常的