Android的自動下拉輸入元件AutoCompleteTextView—SQLite延伸內容2

By | 2016-07-03

在搜尋網站上常見的自動完成輸入方塊可以在使用者不用打出完整的字時,即會出現符合條件的關鍵字清單,而Android也有這樣的元件,稱為「AutoCompleteTextView」,由類別名稱的字面上即可看出它的功用為何,外觀如下圖:

A7318

本篇範例則是延續這兩篇文章:

「Android高效入門—SQLite資料庫」

「Android的日期選擇元件DatePicker—SQLite延伸內容1」

加入AutoCompleteTextView元件

在本系列的Atm專案的消費記錄功能,其中在新增消費資料時,使用者得要自行輸入該筆消費的說明文字,如早餐、停車費等,只是一般人常見的消費就那幾項,假如可以將原本的EditText元件更換為AutoCompleteTextView元件後,使用者應該會更愛用你的APP,以下就開始介紹如何在APP中使用自動完成元件。

本篇的範例延用Atm專案,請使用git取得:

檔案庫(Repository): https://github.com/android66/Atm.git
版本名稱: DatePicker

請先將舊的EditText元件的visibility屬性值設定為gone:

A7314

再到左邊的元件選擇區的Expert分類中點擊AutoCompleteTextView並放置到畫面中,如下圖:

A7315

完成後的預覽圖如下,元件顯示預設字樣,可連擊元件後,將text屬性設為空字串:

A7316

請開啟「java/com.tom.atm/AddActivity.java」,在findViews方法中加入取得AutoCompleteTextView元件的程式碼,並將其提升為類別的屬性,名稱為autoInfo,如下:

public class AddActivity extends AppCompatActivity {
    ...
    private AutoCompleteTextView autoInfo;

    private void findViews() {
        edDate = (EditText) findViewById(R.id.ed_date);
        edInfo = (EditText) findViewById(R.id.ed_info);
        edAmount = (EditText) findViewById(R.id.ed_amount);
        datePicker = (DatePicker) findViewById(R.id.datePicker);
        autoInfo = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView);
    }
    ...
}

使用字串陣列

AutoCompleteTextView元件會在使用者輸入部份內容後,以下拉清單顯示所有符合條件的資料,而它身上的資料使用的也是Adapter家族。

提示

Android的Adapter是很重要的基礎知識,瞭解它的使用與角色能在日後遇到各類需求時,得以解決問題,可參考以下文章:

Android清單元件介紹(ListView-Adapter)

清單元件實作-下拉式選單Spinner

清單元件實作-清單式功能表

最簡單的方式是使用字串陣列,也可以使用資源中的字串陣列,本例為求簡單化,在類別中建立一個setupAdapter方法,在這個方法中加入ArrayAdapter的設計,如下:

public class AddActivity extends AppCompatActivity {
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add);
        findViews();
        setupAdapter();
        helper = MyDBHelper.getInstance(this);
    }

    private void setupAdapter() {
        String[] infos = {"Breakfast", "Bread", "Lunch", "Parking", "Bill"};
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                this,
                android.R.layout.simple_list_item_1,
                infos);
        autoInfo.setAdapter(adapter);
    }
    ...
}

執行後,請在AutoCompleteTextView元件中輸入「br」兩個字,它會自動出現下拉清單,列出符合的資料,也就是以br開頭的Breakfast與Bread,如下圖:

A7318

如果不希望使用者打太多字,如第一個字就要它出現下拉清單,請將AutoCompleteTextView元件的「completionThreshold」屬性設為1,如下圖:

A7320

執行後在AutoCompleteTextView元件中輸入「b」一個字後,即會出現符合的下拉清單資料,如下圖:

A7319

假如設定Threshold值為0不就會直接出現下拉清單了嗎?不是的,說明文件中規定Threshold值一定要大於0,那要如何實作呢? 可以在程式中呼叫showDropDown()方法讓它出現,也可以覆寫AutoCompleteTextView的預設方法來達成這個目的。

呼叫showDropDown方法:

private void setupAdapter() {
    String[] infos = {"Breakfast", "Bread", "Lunch", "Parking", "Bill"};
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(
            this,
            android.R.layout.simple_list_item_1,
            infos);
    autoInfo.setAdapter(adapter);
    autoInfo.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            autoInfo.showDropDown();
        }
    });
}

執行後,在輸入方塊中按兩次(第一次為聚焦Focus,第二次為onClick),即出現下拉清單,並顯示所有符合的資料,如下圖:

A7321

本階段完成的專案在GitHub上的資訊為:

檔案庫(Repository): https://github.com/android66/Atm.git
版本名稱: AutoCompleteTextView-字串陣列

使用資料庫查詢結果

上述範例使用字串陣列儲存在自動完成輸入方塊的下拉清單中的資料,此方法適合做為範例,而實務中比較常將資料放在SQLite資料庫中,將常用消費名稱先建立在資料庫中,使用一個名稱為infos的表格,儲存簡單的名稱資料info欄位。請開啟之前文章中實作完成的MyDBHelper類別,在原本的onCreate方法中加入建立infos表格與新增資料的程式碼,如下:

public class MyDBHelper extends SQLiteOpenHelper{
    ...
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE  TABLE main.exp " +
                "(_id INTEGER PRIMARY KEY  NOT NULL , " +
                "cdate DATETIME NOT NULL , " +
                "info VARCHAR, " +
                "amount INTEGER)");
        db.execSQL("CREATE TABLE infos " +
                "(_id INTEGER PRIMARY KEY  NOT NULL , " +
                "info VARCHAR NOT NULL)" );
        String[] infos = {"Breakfast", "Bread", "Lunch", "Parking", "Bill"};
        for (String info : infos) {
            ContentValues values = new ContentValues();
            values.put("info", info);
            db.insert("infos", null, values);
        }
    }
	...
}

提示

更改了SQLiteOpenHelper內的onCreate方法後,請記得要將模擬器中測試的APP移除安裝,否則下次執行時是不會執行onCreate的,infos表格也不會事先建立。

回到AddActivity類別中,現在因為在設定Adapter之前需要取得helper物件,請到onCreate方法中改變執行順序,如下:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_add);
    findViews();
    helper = MyDBHelper.getInstance(this);
    setupAdapter();
}

再到自行建立的setupAdapter方法中,實作SimpleCursorAdapter程式碼,如下:

private void setupAdapter() {
    Cursor cursor = helper.getReadableDatabase()
            .query("infos", null, null, null, null, null, null);
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(
            this,
            android.R.layout.simple_list_item_1,
            cursor,
            new String[]{"info"},
            new int[]{android.R.id.text1}, 0);
    autoInfo.setAdapter(adapter);
    autoInfo.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            autoInfo.showDropDown();
        }
    });
}

執行結果如下圖,與之前的相同,但資料是由SQLite讀取得到:

A7322

提示

SimpleCursorAdapter的介紹與實作可參考Android高效入門>深度學習一書中的第九章 SQLite資料庫,或參考文章:

「Android高效入門—SQLite資料庫」

本階段完成的專案在GitHub上的資訊為:

檔案庫(Repository): https://github.com/android66/Atm.git
版本名稱: AutoCompleteTextView-SQLite表格

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *