原文:http://my.oschina.net/freestyletime/blog/113149
效果图先摆上,其中只有一个关键字,但无论几个都行的,作者已然测试了很多遍。

最近要做一个名词解释的功能:在一段文本里有N个关键名词,这些关键名词需要将这段文本与本地数据库相比较后得到。
1 | public PhraseItem( long id, String name) { |
这个Bean中有两个属性,分别代表在数据库中的ID(方便以后查),和关键词,比如:窦性心率过速。
1 | public Map<Integer, PhraseItem> searchKeyWords(String string) |
该函数将识别一段文本中的所有关键字, 返回一个TreeMap (自动排序),其中的key值代表该关键字的Index。
01 | final Map<Integer, PhraseItem> keywords = mKeyWordManger.searchKeyWords(content); |
03 | Set<Entry<Integer, PhraseItem>> entrys = keywords.entrySet(); |
07 | for (Entry<Integer, PhraseItem> entry : entrys) { |
09 | start = entry.getKey(); |
10 | key = entry.getValue().getName(); |
12 | tv_msg.append(content.substring(count, start)); |
13 | tv_msg.append(Html.fromHtml( "<a href=" + start + " ><u>" + key |
16 | count = start + key.length(); |
19 | tv_msg.append(content.substring(count)); |
其中的tv_msg是TextView,它有一个append函数,可以不断的向其中添加可视文本。
我遍历了整个关键字的Map , 因为它本身是TreeMap ,所以里面的Entry已经帮你按key值的大小从小到大帮你排好了序。所以可以从容的对一段文本中的普通文本与关键字进行切割。
置于For循环以外的tv_msg.append(content.substring(count))指的是添加在最后一个关键字以后的普通文本,这是必须要加的,否则整个文本将不完整。这还是很简单的,
不过关键的地方在于tv_msg.append(Html.fromHtml("<a href=" + start + " ><u>" + key + "</u></a>"));
我们将利用这句话给关键字加下划线,利用其中的href属性识别关键字为进行点击做准备。
01 | tv_msg.setMovementMethod(LinkMovementMethod.getInstance()); |
02 | CharSequence text = tv_msg.getText(); |
04 | if (text instanceof Spannable) { |
05 | int end = text.length(); |
06 | Spannable sp = (Spannable) text; |
07 | URLSpan[] urls = sp.getSpans( 0 , end, URLSpan. class ); |
08 | SpannableStringBuilder style = new SpannableStringBuilder(text); |
10 | for ( final URLSpan url : urls) { |
14 | public void onClick(View keyView) { |
15 | PhraseItem word = keywords.get(Integer.valueOf(url.getURL())); |
16 | Intent mIntent = new Intent(MessageActivity. this ,KeyWordActivity. class ); |
17 | mIntent.putExtra(KeyWordActivity.KEY_NAME,word.getName()); |
18 | mIntent.putExtra(KeyWordActivity.KEY_INFOS, |
19 | mKeyWordManger.searchPhrase(word.getId())); |
20 | startActivity(mIntent); |
21 | }}, sp.getSpanStart(url), sp.getSpanEnd(url), |
22 | Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
24 | tv_msg.setText(style); |
这个从数据库到前台做了3天,查阅了好些资料经过各种尝试才搞出来的。想要把名词解释变的很简单,必须得好好设计一下数据库的表结构才行,如果你还想点击后让超链接变色,可以尝试重写TextView的onTouch事件,这个很复杂了,不过是可以实现的。或者给<a/>标签添加style属性,这个得熟悉CSS,作者没试过这种方法,大家可以试试。
这里是Freestyletime@foxmail.com,欢迎交流。
本人原创作品,转载请标明出处。
续:点击后让超链接变色楼主已经找到了解决方法!!!
上图:

在项目的维护过程中,楼主想到了一个简单的办法解决了超链接点击后无法变色以提醒用户看过该信息的功能。
04 | private boolean isClick = false ; |
08 | public void updateDrawState(TextPaint ds) { |
11 | ds.setColor(Color.GREEN); |
14 | ds.setColor(Color.RED); |
16 | ds.setUnderlineText( true ); |
20 | public void onClick(View keyView) { |
24 | PhraseItem word = keywords.get(Integer |
25 | .valueOf(url.getURL())); |
27 | Intent mIntent = new Intent( |
29 | KeyWordActivity. class ); |
31 | mIntent.putExtra(KeyWordActivity.KEY_NAME, |
33 | mIntent.putExtra(KeyWordActivity.KEY_INFOS, |
34 | mKeyWordManger.searchPhrase(word |
37 | startActivity(mIntent); |
42 | }, sp.getSpanStart(url), sp.getSpanEnd(url), |
43 | Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
让你的ClickableSpan再点击后再次调用内部的updateDrawState这个方法更新一下当前文本颜色即可,简单吧!!
有什么更好的可以提出大家一起讨论。