解决 ListView的Item里TextView设置超链接后ListView 的OnItemClick失效的问题

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

1
2
3
4
5
TextView tv = (TextView)findViewById(R.id.tv);
SpannableString sp =  new  SpannableString( "此处为tv里显示的内容" );
sp.setSpan(  new   URLSpan(  "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的源码文件,截取的关键代码片段如下:

wKioL1LHkTyjKLGQAACZ9Ux9MIg927.jpg650) this.width=650;" οnsubmit="" οnchange="" has_check_key_word="true" οnunlοad="" οnselect="" οnreset="">

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
   @Override
public  boolean  onTouchEvent(TextView widget, Spannable buffer,
                             MotionEvent event) {
     int  action = event.getAction();
     if  (action == MotionEvent.ACTION_UP ||
         action == MotionEvent.ACTION_DOWN) {
         int  x = ( int ) event.getX();
         int  y = ( int ) event.getY();
         x -= widget.getTotalPaddingLeft();
         y -= widget.getTotalPaddingTop();
         x += widget.getScrollX();
         y += widget.getScrollY();
         Layout layout = widget.getLayout();
         int  line = layout.getLineForVertical(y);
         int  off = 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);
             else  if  (action == MotionEvent.ACTION_DOWN) {
                 Selection.setSelection(buffer,
                                        buffer.getSpanStart(link[ 0 ]),
                                        buffer.getSpanEnd(link[ 0 ]));
             }
             return  true //处理结束后返回true,这里一定要注意:当返回值为true时则表示点击事件已经被,就再也不会继续传递了
         else  {
             Selection.removeSelection(buffer);
         }
     }
     return  super .onTouchEvent(widget, buffer, event);
}

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

wKiom1LHlTzxAlYtAAA2uld9Jrk531.jpg650) this.width=650;" οnsubmit="" οnchange="" has_check_key_word="true" οnunlοad="" οnselect="" οnreset="">

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

wKioL1LHldywWR1tAAE4WGfZtn4031.jpg650) this.width=650;" οnsubmit="" οnchange="" has_check_key_word="true" οnunlοad="" οnselect="" οnreset="">

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

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

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

欢迎加入QQ讨论群:285077071

本文出自 “严富坤-编程技术” 博客,请务必保留此出处http://kinbos.blog.51cto.com/2092114/1348407

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值