Android 使用 AutoCompleteTextView 搭配 SQLite 取得曾經輸入的資料
為了讓輸入資料時更方便,試著使用了 AutoCompleteTextView 想讓 App 自動顯示以前輸入過的資料。
首先需要設定 AutoCompleteTextView 的 Adapter,一般的範例都使用 SimpleCursorAdapter。
但是我們可以發現到,它會列出所有該欄位的內容,這樣子使用者先輸入的文字就沒有意義了。
原本想直接在 Cursor 設定 query 的條件,但沒想到竟然無效!不得已只好另尋它法,於是就在 SimpleCursorAdapter 找到了 setFilterQueryProvider。
這邊有兩個重點要注意:
第一是根據 SimpleCursorAdapter 的父類別 CursorAdapter 的設計,資料的欄位(Column)必須包含「_id」這個名字的欄位,所以在 SQL 指令的 SELECT 後必須加入「_id」。
第二個則是使用者體驗的考量,不要讓結果出現重複的內容;這可以在 SQL 指令中使用「GROUP BY」來實現。
下面左圖為沒有 GROUP BY,右圖則有使用 GROUP BY:
到這邊看似已經完成了吧?但其實還有最後一個坑!
點選自動完成的內容後,得到的不是想像中的文字,而是類似物件位址的一長串字!
原因是前面 setFilterQueryProvider 得到的是 Cursor,而我們必須再從中取出需要的資料。
這邊使用的是 setCursorToStringConverter。
做到這一步,終於完成了
首先需要設定 AutoCompleteTextView 的 Adapter,一般的範例都使用 SimpleCursorAdapter。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Cursor cursor = dbHelper.getReadableDatabase() | |
.query(TABLE_EXPENSE, null, null, null, null, null, null); | |
SimpleCursorAdapter adapter = new SimpleCursorAdapter( | |
this, | |
android.R.layout.simple_list_item_1, | |
cursor, | |
new String[]{COLUMN_MAIN_NAME}, | |
new int[]{android.R.id.text1}, | |
0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AutoCompleteTextView textName = findViewById(R.id.text_name); | |
textName.setAdapter(adapter); |
原本想直接在 Cursor 設定 query 的條件,但沒想到竟然無效!不得已只好另尋它法,於是就在 SimpleCursorAdapter 找到了 setFilterQueryProvider。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
adapter.setFilterQueryProvider(new FilterQueryProvider() { | |
@Override | |
public Cursor runQuery(CharSequence constraint) { | |
Cursor cursor = null; | |
if (constraint != null) { | |
// Cause by the design of CursorAdapter, query must contain column "_id". | |
cursor = dbHelper.getReadableDatabase().rawQuery( | |
"SELECT " + COLUMN_MAIN_ID + ", " + COLUMN_MAIN_NAME + | |
" FROM " + TABLE_EXPENSE + | |
" WHERE " + COLUMN_MAIN_NAME + " LIKE '%" + name + | |
"%' GROUP BY " + COLUMN_MAIN_NAME, null); | |
} | |
return cursor; | |
} | |
}); |
第一是根據 SimpleCursorAdapter 的父類別 CursorAdapter 的設計,資料的欄位(Column)必須包含「_id」這個名字的欄位,所以在 SQL 指令的 SELECT 後必須加入「_id」。
第二個則是使用者體驗的考量,不要讓結果出現重複的內容;這可以在 SQL 指令中使用「GROUP BY」來實現。
下面左圖為沒有 GROUP BY,右圖則有使用 GROUP BY:
到這邊看似已經完成了吧?但其實還有最後一個坑!
點選自動完成的內容後,得到的不是想像中的文字,而是類似物件位址的一長串字!
原因是前面 setFilterQueryProvider 得到的是 Cursor,而我們必須再從中取出需要的資料。
這邊使用的是 setCursorToStringConverter。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
adapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter() { | |
@Override | |
public CharSequence convertToString(Cursor cursor) { | |
return cursor.getString(1); | |
} | |
}); |
留言
張貼留言