Spannable做富文本部分点击时跳转,类似于QQ的点赞好友的点击跳转效果.QQ空间的图片
实现代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView t1 = (TextView) findViewById(R.id.tv1);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 20; i++) {
sb.append("基友" + i + "、");
}
String friends = sb.substring(0, sb.lastIndexOf("、")).toString();
t1.setMovementMethod(LinkMovementMethod.getInstance());
t1.setText(addClickPart(friends), TextView.BufferType.SPANNABLE);
}
// 定义一个点击每个部分文字的处理方法
private SpannableStringBuilder addClickPart(String str) {
SpannableStringBuilder ssb = new SpannableStringBuilder(str);
String[] friends = str.split("、");
if (friends.length > 0) {
for (int i = 0; i < friends.length; i++) {
final String name = friends[i];
final int start = str.indexOf(name) ;
if(start != -1) {
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(MainActivity.this, name,
Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
//删除下划线,设置字体颜色为红色
ds.setColor(Color.RED);
ds.setUnderlineText(false);
}
}, start, start + name.length(), 0);
}
}
}
return ssb.append("等" + friends.length + "个人觉得很赞");
}
}
布局文件比较简单这里就不粘了,就是一个TextView.
效果如下:
其中LinkMovementMethod.的解释如下:
比如它的onKeyDown调用ClickableSpan的onClick
URLSpan实现了ClickableSpan
用户点击一个url的话,就会调用LinkMovementMethod::onKeyDown,继而调用URLSpan的onClick,
我们看看URLSpan::onClick的实现
@override
public void onClick(View widget) {
Uri uri = Uri.parse(getURL());
Context context = widget.getContext();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
context.startActivity(intent);
}
它实际上是启动了一个activity,可能是web/email或者其他的满足intent filter/url schema的activity.
以下是本猿的教训:
啥话不说直接上代码想不到displayName的用处,只想着用来和输入的msgText来作对比想匹配,还搞了个正则表达式,遍历了两次功能虽然是实现了但是却是很麻烦,自己想不到其实 final String name = stockList[i];是可以用listStock来替换的.脑子真的转的很慢.
// Pattern p = Pattern.compile("( \\$)(.*?)(\\$ )");
// Matcher matcher = p.matcher(ssb);
// List list = new ArrayList();
// int j = 0;
// while (matcher.find()) {
// searchStocks = listStock.get(j);
// String sel = matcher.group();
// if (searchStocks.getDisplayname().equals(sel)) {
// list.add(matcher.group());
// j++;
// }
// }
// String[] stockList = (String[]) list.toArray(new String[0]);
// MyLog.e("pipei " + Arrays.toString(stockList));
//
// if (stockList.length > 0) {
// for (int i = 0; i < stockList.length; i++) {
//
// final String name = stockList[i];
// final int start = str.indexOf(name);
// ssb.setSpan(new ClickableSpan() {
// @Override
// public void onClick(View widget) {
// Toast.makeText(context, name,
// Toast.LENGTH_SHORT).show();
// }
//
// @Override
// public void updateDrawState(TextPaint ds) {
// super.updateDrawState(ds);
// ds.setUnderlineText(true);
// }
// }, start, start + name.length(), 0);
// }
// }
SpannableStringBuilder ssb = new SpannableStringBuilder(str);
for (int i = 0; i < listStock.size(); i++) {
StockElem.SearchStocks searchStocks = listStock.get(i);
final String disPlayName = searchStocks.getDisplayname();
final int start = str.indexOf(disPlayName);
if (start != -1) {
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(context, disPlayName,
Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(true);
}
}, start, start + disPlayName.length(), 0);
}
}