最近在做項目研發過程中有這樣一個需求:ListView的Item裏的子控件TextView要設置超鏈接、指定文字高亮顯示,然後點擊超鏈接後跳轉到指定URL的網頁。實現超鏈接的跳轉這很容易,只要通過對TextView設置SpannableString對象即可,即如下代碼:
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的源碼文件,截取的關鍵代碼片段如下:
該代碼片段是TextView源碼的第1421行(Android4.2.2版本),我們發現不能通過重寫此方法來解決我們所面臨的問題,再繼續跟蹤LinkMovementMethod這個類吧,關鍵源碼如下:
@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一下,終於找到國外的一個網站,上面的文章標題是:
此時此刻的心情真是如獲至寶呀……接着看下去……發現有高人是這樣解決的:
發現這位高人本質思路是我們開始分析的本質思路一樣,只不過他把要處理的代碼放在了TextView的onTouch方法裏,然後根據不同的情況返回true或false.在getView()方法裏對相應的TextView進行設置吧,Run app……見證奇蹟的時刻到了……哈哈,結果真的能行了,耶哦!
經過此劫,我發現了爲什麼國外的技術總是比國內要先進得多了,我在此並不是貶低同僚,不支持國產,而是在國內的技術普遍都是你抄我,我抄你的,有的甚至連原文鏈接都不放……大家可以看看國外這個技術網站人家是怎麼解決問題的,真是按部就班,循序漸進的,不僅讓你知其然還知其所以然。
歡迎加入QQ討論羣:285077071