顯示具有 AutoCompleteTextView 標籤的文章。 顯示所有文章
顯示具有 AutoCompleteTextView 標籤的文章。 顯示所有文章

2008年7月28日 星期一

在 Android 上利用 Google APIs 實現 Google Suggestion 功能

Using Google APIs to implement Google Suggest functions on Android platform.

這篇是屬於偏向教學性質的文章。在這篇,我將示範的是,如何利用 Google APIs,做出和 Google Suggest 一樣,會依照你輸入的部份字元,自動列出建議關鍵字的程式。這個程式的執行畫面,就像下面這樣。

在 Google 提供的眾多服務中,Google Suggest 是我自己很常用的功能之一,他可以幫我列出那些關鍵字是最常被使用的。如果你還沒用過,他的網址在這:http://www.google.com/webhp?complete=1&hl=zh-tw。你可以自己上去試用看看。

在開始介紹要如何寫出這樣一個程式之前,你會需要用到下面這些背景知識,我建議你要先讀過這些文章:

除了這些,在這篇教學中,你將會學到:

  • 如何用 HttpURLConnection 抓取網路服務所提供的資料。
  • 如何用 Handler 處理 Non-UI thread 的 UI 更新要求。
  • 如何用 Html.fromHtml() 在 TextView 上顯示簡單的 HTML 格式。

如何取得 Google Suggest 的建議關鍵字資料?

首先,要先知道如何取得這 Google Suggest 的建議關鍵字資料。要取得這建議關鍵字,你可以透過這個 URL,http://www.google.com/complete/search?xml=true&q=你的部份關鍵字字元。由於我們希望他傳回的是 XML 格式,因此在這個 URL 上要加上 xml=true這個查詢參數。例如 http://www.google.com/complete/search?xml=true&q=andr 這個 URL,所傳回的結果如下:

看到沒,這 suggestion data="android" 內的 data 資料,就是我們要的建議關鍵字。而 num_queries int="22500000" 內的 int 數目,則代表有多少和這個關鍵字相關的結果。

如何用 HttpURLConnection 抓取網路服務所提供的資料?

關於這 XML 格式的結果,待會我再說明,如何利用 DOM API,將我們要的資料抽取出來。我先說如何用 HttpURLConnection 去抓取這資料。先看下面這個程式片段:

在第 10~11 行中,我們先利用 URLEncoder.encode() 產生包含查詢字串的完整 URL 地址,並產生個 URL 物件。在 14 行中,用 URL.openConnection(),打開一個 HttpURLConnection 連結物件。有了這個物件,接著的 getResponseCode(),就會實際連到你所指定的網址,並將你所指定的頁面資料傳回來。這傳回的資料,就在第 19 行 http.getInputStream() 所傳回的 InputStream 內。最後的第 21~24 行,就是在將這傳回的 XML 資料,轉成 Document 物件。之後,我們就可以用 DOM APIs,抽出我們要的資料。

如何解析 XML 資料並轉成 DOM?

底下的程式片段說明如何用 DOM APIs,抽出我們要的建議關鍵字及其結果數量。

所有抽出來的建議關鍵字其數量值,都放在 alSuggWord 和 alSuggVal 這兩個 ArrayList 中。底下的程式,則是簡單地依照數量值重新排序最後的結果。我們要的,當然是數量最多的排第一。

如何客製化 AutoCompleteTextView 中的 Filter 功能?

我們知道,每當你在 AutoCompleteTextView 中輸入一個字元,他都會呼叫 Filter 類別的 performFiltering() 函式,讓你自己過濾所要顯示的結果。由於我們希望所有的結果,都是透過 Google Suggest API 所要回來的。因此我們在這個函式中,主要就是呼叫前面介紹過的 GoogleSuggestiong.Get() 取得所有的建議關鍵字。

如何用 Handler 處理 Non-UI thread 的 UI 更新要求?

在大多數的 single thread GUI framework 上,都會規定你不能在這個寶貴的 UI thread 中,花太長的時間來執行某段程式處理,Android 也是如此。如果你真的違反這個規定,那你的使用者就會看見 ANR (Application is Not Responding) 這個警告訊息。

這個的解法就是將原先要花許多時間處理的程式移到另一個 non-UI thread 上。

不過,另外一個問題來了。在 Android 中,只有 UI thread 可以呼叫 UI 物件所提供的函式。例如,在這個範例中,在取得建議關鍵字的過程中,我們都會呼叫 _UpdateStatus(),顯示目前的進度狀態。不過由於 Filter.performFiltering() 在 Android 的設計上,他是被另一個 Non-UI thread 所呼叫的。因此在 _UpdateStatus() 中,你可不可以直接呼叫 TextView 的 setText() 函式。我的解法就是在 Non-UI thread 中,透過 Handler,傳送一個 message 到 UI thread 的 handler 處理函式,讓 UI thread 來處理 View 類別的相關顯示工作。底下是關於這個處理的程式片段:

如何用 Html.fromHtml() 在 TextView 上顯示簡單的 HTML 格式?

TextView 其實提供了許多好用的功能,其中最棒的是,他還允許你顯示簡單的 HTML 格式。你只要傳個 Spanned 物件給 setText() 即可。在 Android 上,有許多 APIs 都可以幫助你產生,Spanned 物件,不過我最常用的就是 Html.fromHtml(),原因就是他簡單好用。看了底下的程式片段,你應該就會用了。

最後,底下是關於 sugg.xml 檔的內容。

這個範例程式,只做到列出候選的建議關鍵字讓你選。至於 action 函式,就請你發揮自己的創意繼續完成他囉。


繼續閱讀全文...

2008年7月7日 星期一

客製化 AutoCompleteTextView 中的 Filter 功能

How to customize the filtering function for AutoCompleteTextView widget?

這裡 我提過,另一個縮小 AutoCompleteTextView 的方法,就是自己寫個 ArrayAdapter,然後在 getView() 中,產生個 TextView 給 AutoCompleteTextView。這簡單的程式片段,大致如下。在 getView() 函式中,自己 new 個 TextView widget。

不過,要寫個可以給 AutoCompleteTextView 用的 ArrayAdapter,可沒表面上看起來那麼地簡單。因為,你還要在這個類別裡,寫個 Filterable 介面的實現才行。

這個 Filterable interface 就是用來,從現有的全部結果中,依照你輸入的字元,過濾出符合的結果。而 AutoCompleteTextView ,則只單純地列出 Filterable 所傳回的結果。例如,當你輸入個 B 字元時,AutoCompleteTextView 就藉由 Filterable 的函式,列出只有 B 開頭的國家。這也是 AutoCompleteTextView 中,最主要的功能。

不過,如果你想要列出所有的國家,AutoCompleteTextView 目前可沒這樣的功能。最簡單的方式,就是自己寫個 Filterable 的實現。所以啦,Filterable 可不是只能用來過濾結果。你可拿它來做任何事,AutoCompleteTextView 根本不管他傳回的內容是什麼,他只單純地列出 Filterable 所傳回的結果。

延續 這裡 的例子,我將他改成,如果只輸入 "*" 這個字元,就列出所有的國家。如果是其他字元,就依照原先的用法,列出符合輸入字元的國家。

在 Filterable 這個介面中,你要實現這兩個方法。

底下就是,如何在這兩個函式中,實現用 "*" 列出所有國家。

還沒完,接下來,你還要在你自己的 ArrayAdapter (這裡的 CntyListAdapter),實現下列的方法才行。

好了,最後的執行結果就像這樣。你想到要利用 Filterable ,來做出什麼特別功能嗎?


繼續閱讀全文...

2008年6月27日 星期五

親愛的,我把 AutoCompleteTextView 縮小了

Yes! I finally can change the size of AutoCompleteTextView.

Android SDK 中有個好用的 AutoCompleteTextView widget。寫起來簡單,不用幾行程式,就可以完成一個有具有自動完成的編輯器。 底下是原文件上的範例程式,和截圖。為了說明問題,我又多加了幾個國家名稱。

現在問題來了,這預設的 auto complete list 似乎太大了。一個螢幕列出兩個國家就滿了。手機螢幕大的話,問題不大。要是手機是小螢幕,這可就難用了。

要如何才能將這 list 的高度縮小,一次列出更多的國家呢?

研究了半天,發現問題出在 android.R.layout.simple_list_item_1

android.R.layout 告訴我,這是 Android 預附的 layout xml 檔。花了點時間,終於找到這個檔案,其內容如下:

原來這 auto complete list 中的 TextView,就是依照這個 xml 的定義來產生。要改變 TextView 的大小,可以加個 android:textSize="14sp"。底下就是我新增的 small_list_item_1.xml 檔。將他放在 layout 的目錄下。

並且將原程式中的第 5~6 行,改成: 這是改完後的結果,是不是好多了。

要修改 list 的大小,這是最簡單的方法。另一個方法是自己寫個 ArrayAdapter,然後在 getView() 中,產生個 TextView 給 AutoCompleteTextView。


繼續閱讀全文...