最近在做项目研发过程中有这样一个需求:ListView的Item里的子控件TextView要设置超链接、指定文字高亮显示,然后点击超链接后跳转到指定URL的网页。实现超链接的跳转这很容易,只要通过对TextView设置SpannableString对象即可,即如下代码:

TextViewtv=(TextView)findViewById(R.id.tv);SpannableStringsp=newSpannableString("此处为tv里显示的内容");sp.setSpan(newURLSpan("http://www.baidu.com"),3,8,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);tv.setText(sp);tv.setMovementMethod(LinkMovementMethod.getInstance());

通过这样的设置后已经能够实现对超链接点击跳转到指定URL的网页了,可麻烦又来了,你会发现点击ListView里的Item时没有任何反应,这是什么原因呢?还记得上面在设置超链接的时候有这样一条语句:tv.setMovementMethod(LinkMovementMethod.getInstance());我们现在把这条语句注释掉看看……run App,结果点击Item的时候能够响应了,可惜超链接又失效了,任你点击也没有响应了,哎,真可谓是“鱼和熊掌不可兼得”。现在已经断定Item失效的原因何在了,那为什么这条语句就会导致Item点击失效呢?源码往往是揭开程序中各种奇芭问题的尖锐利器,让我们跟踪下源码吧……打开TextView的源码文件,截取的关键代码片段如下:

该代码片段是TextView源码的第1421行(Android4.2.2版本),我们发现不能通过重写此方法来解决我们所面临的问题,再继续跟踪LinkMovementMethod这个类吧,关键源码如下:

@OverridepublicbooleanonTouchEvent(TextViewwidget,Spannablebuffer,MotionEventevent){intaction=event.getAction();if(action==MotionEvent.ACTION_UP||action==MotionEvent.ACTION_DOWN){intx=(int)event.getX();inty=(int)event.getY();x-=widget.getTotalPaddingLeft();y-=widget.getTotalPaddingTop();x+=widget.getScrollX();y+=widget.getScrollY();Layoutlayout=widget.getLayout();intline=layout.getLineForVertical(y);intoff=layout.getOffsetForHorizontal(line,x);//获取textview里的超链接对象,并用ClickableSpan数组盛装ClickableSpan[]link=buffer.getSpans(off,off,ClickableSpan.class);if(link.length!=0){//此处是对超链接点击事件进行处理……if(action==MotionEvent.ACTION_UP){link[0].onClick(widget);}elseif(action==MotionEvent.ACTION_DOWN){Selection.setSelection(buffer,buffer.getSpanStart(link[0]),buffer.getSpanEnd(link[0]));}returntrue;//处理结束后返回true,这里一定要注意:当返回值为true时则表示点击事件已经被,就再也不会继续传递了}else{Selection.removeSelection(buffer);}}returnsuper.onTouchEvent(widget,buffer,event);}

上述源码为LinkMovementMethod类的第188行。发现了Item点击失效的原因是因为onTouch方法总是返回true而并没有根据不同的情况来作处理,此时大家可能会想直接对这个方法重写就能解决问题了。我和大家想的也一样,对该方法重写,并根据情况返回true或false,遗憾的是还是没有效果,并且在重写的方法里看不到输出的日志信息,暂时不明其中原因,请高手赐教!眼看就要看到光明了,可还是被打击了……不要灰心,面包总是会有的,如果你不放弃的话,哈哈。换个keywords google一下,终于找到国外的一个网站,上面的文章标题是:

此时此刻的心情真是如获至宝呀……接着看下去……发现有高人是这样解决的:

发现这位高人本质思路是我们开始分析的本质思路一样,只不过他把要处理的代码放在了TextView的onTouch方法里,然后根据不同的情况返回true或false.在getView()方法里对相应的TextView进行设置吧,Run app……见证奇迹的时刻到了……哈哈,结果真的能行了,耶哦!

原文链接:http://stackoverflow.com/questions/8558732/listview-textview-with-linkmovementmethod-makes-list-item-unclickable

经过此劫,我发现了为什么国外的技术总是比国内要先进得多了,我在此并不是贬低同僚,不支持国产,而是在国内的技术普遍都是你抄我,我抄你的,有的甚至连原文链接都不放……大家可以看看国外这个技术网站人家是怎么解决问题的,真是按部就班,循序渐进的,不仅让你知其然还知其所以然。

欢迎加入QQ讨论群:285077071