基于Android的英文詞典的實現(xiàn)方法
英文詞典是手機中經(jīng)常使用的應(yīng)用。因此,在本文將結(jié)合Android來討論如何實現(xiàn)一個Android版的英文詞典。實現(xiàn)英文詞典的方法很多。在本文使用了SQLite數(shù)據(jù)庫來保存英文單詞信息。系統(tǒng)通過SQLite數(shù)據(jù)庫中保存的單詞信息來查找到與指定英文對應(yīng)的中文信息。當然,實現(xiàn)這樣一個英文詞典需要解決一系列技術(shù)問題。例如,如何將保存英文單詞信息的數(shù)據(jù)庫文件隨程序(apk文件)一起發(fā)布;發(fā)布后如何打開數(shù)據(jù)庫;如何在輸入前幾個字母后,在AutoCompleteTextView組件提示列表中顯示以所輸入字符串開頭的所有單詞。在本章將逐漸給出這些問題的詳細答案。
實現(xiàn)電子詞典要解決的技術(shù)問題及初步的解答
在這里將給出實現(xiàn)電子詞典需要解決的主要技術(shù)問題,并給出這些技術(shù)問題的初步答案或提示。
關(guān)于詳細的答案和代碼請讀者參閱本文后面的內(nèi)容。
主要技術(shù)問題及解答如下:
1. 如何將SQLite數(shù)據(jù)庫(dictionary.db文件)與apk文件一起發(fā)布?
解答:可以將dictionary.db文件復(fù)制到Eclipse Android工程中的res\raw目錄中,如圖1所示。所有在res\raw目錄中的文件不會被壓縮,這樣可以直接提取該目錄中的文件。
圖1 將dictionary.db文件復(fù)制到res\raw目錄中
2. 如何將打開res\raw目錄中的數(shù)據(jù)庫文件?
解答:在Android中不能直接打開res\raw目錄中的數(shù)據(jù)庫文件,而需要在程序第一次啟動時將該文件復(fù)制到手機內(nèi)存或SD卡的某個目錄中,然后再打開該數(shù)據(jù)庫文件。復(fù)制的基本方法是使用getResources().openRawResource方法獲得res\raw目錄中資源的InputStream對象,然后將該InputStream對象中的數(shù)據(jù)寫入其他的目錄中相應(yīng)文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法來打開任意目錄中的SQLite數(shù)據(jù)庫文件。
3. 如果在AutoCompleteTextView組件中輸入兩個及以上字母時顯示以所輸入字符串開頭的所有單詞列表?
解答:AutoCompleteTextView所使用的Adapter是一個自定義的Adapter類,類的結(jié)構(gòu)如下:
public class DictionaryAdapter extends CursorAdapter { }
要注意的是,不能將整個數(shù)據(jù)庫中的單詞都查出,然后生成一個Adapter對象再使用setAdapter方法來設(shè)置AutoCompleteTextView組件的Adapter對象。AutoCompleteTextView組件不會為我們篩選以某個字符串開頭的單詞。這些工作需要開發(fā)人員通過編碼來實現(xiàn)。
基本思路是在AutoCompleteTextView類的afterTextChanged事件中監(jiān)視AutoCompleteTextView組件中字符的輸入情況,每當輸入一個字符時就生成一個Adapter對象,然后將新生成的Adapter對象與AutoCompleteTextView關(guān)聯(lián)。顯示以輸入字符串開頭的單詞列表的效果如圖2所示。
圖2 顯示以輸入字符串開頭的單詞列表
復(fù)制并打開保存英文單詞的數(shù)據(jù)庫文件
在本文實現(xiàn)的英文詞典中使用openDatabase方法來打開數(shù)據(jù)庫文件(該文件在SD卡的dictionary目錄中,因此,要想運行本文實現(xiàn)的英文 詞典,需要在手機或模擬器中需要安裝SD卡)。如果該文件不存在,系統(tǒng)會自動創(chuàng)建/sdcard/dictionary目錄,并將res\raw目錄中的 dictionary.db文件復(fù)制到/sdcard/dictionary目錄中。openDatabase方法的實現(xiàn)代碼如下:
private SQLiteDatabase openDatabase() { try { // 獲得dictionary.db文件的絕對路徑 String databaseFilename = DATABASE_PATH + "/" + DATABASE_FILENAME; File dir = new File(DATABASE_PATH); // 如果/sdcard/dictionary目錄中存在,創(chuàng)建這個目錄 if (!dir.exists()) dir.mkdir(); // 如果在/sdcard/dictionary目錄中不存在 // dictionary.db文件,則從res\raw目錄中復(fù)制這個文件到 // SD卡的目錄(/sdcard/dictionary) if (!(new File(databaseFilename)).exists()) { // 獲得封裝dictionary.db文件的InputStream對象 InputStream is = getResources().openRawResource(R.raw.dictionary); FileOutputStream fos = new FileOutputStream(databaseFilename); byte[] buffer = new byte[8192]; int count = 0; // 開始復(fù)制dictionary.db文件 while ((count = is.read(buffer)) > 0) { fos.write(buffer, 0, count); } fos.close(); is.close(); } // 打開/sdcard/dictionary目錄中的dictionary.db文件 SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase( databaseFilename, null); return database; } catch (Exception e) { } return null; }
在openDatabase方法中使用了幾個常量,這些常量是在程序的主類(Main)中定義的,代碼如下:
public class Main extends Activity implements OnClickListener, TextWatcher { private final String DATABASE_PATH = android.os.Environment .getExternalStorageDirectory().getAbsolutePath() + "/dictionary"; private final String DATABASE_FILENAME = "dictionary.db"; }
查詢單詞
英文詞典的核心就是查找英文單詞的中文意思。在查找中文意思之前,首先需要使用openDatabase方法在Main類的onCreate方法中打開SQLite數(shù)據(jù)庫,代碼如下:
database = openDatabase();
其中database是在Main類中定義的SQLiteDatabase類型變量。
然后在查找按鈕的單擊事件中添加如下的代碼來查找英文單詞,并顯示中文意思。
public void onClick(View view) { String sql = "select chinese from t_words where english=?"; Cursor cursor = database.rawQuery(sql, new String[] { actvWord.getText().toString() }); String result = "未找到該單詞."; // 如果查找單詞,顯示其中文信息 if (cursor.getCount() > 0) { // 必須使用moveToFirst方法將記錄指針移動到第1條記錄的位置 cursor.moveToFirst(); result = cursor.getString(cursor.getColumnIndex("chinese")); } // 顯示查詢結(jié)果對話框 new AlertDialog.Builder(this).setTitle("查詢結(jié)果").setMessage(result) .setPositiveButton("關(guān)閉", null).show(); }
講到這里我們應(yīng)該了解一個dictionary.db中的t_words表的結(jié)果,該表只有兩個字段:english和chinese。分別表示單詞的英文和中文描述。如果要獲得單詞的中文描述,只需要查找chinese字段即可。如onClick方法中的代碼所示。查詢單詞的效果如圖3所示。
圖3 查詢英文單詞
如果顯示以輸入字符串開頭的單詞列表
雖然到目前為止,我們的英文詞典已經(jīng)可以正常工作了,但為了方便讀者使用,在本節(jié)將添加單詞輸入的自動提示功能。也就是說,如果讀者在 AutoCompleteTextView組件中輸入單詞的前幾個字母,該組件就會自動列出數(shù)據(jù)庫中所有以該字符串開頭的單詞。效果如圖2所示。擁有這樣 的功能就可以使用戶在只知道單詞的前幾個字母時也可以查找到相應(yīng)的單詞。
由于AutoCompleteTextView組件使用了自定義的Adapter類,下面先給出這個自定義的Adapter類的完整代碼。
public class DictionaryAdapter extends CursorAdapter { private LayoutInflater layoutInflater; @Override public CharSequence convertToString(Cursor cursor) { return cursor == null ? "" : cursor.getString(cursor .getColumnIndex("_id")); } // 用于將_id字段(也就是english字段)的值設(shè)置TextView組件的文本 // view參數(shù)表示用于顯示列表項的TextView組件 private void setView(View view, Cursor cursor) { TextView tvWordItem = (TextView) view; tvWordItem.setText(cursor.getString(cursor.getColumnIndex("_id"))); } @Override public void bindView(View view, Context context, Cursor cursor) { setView(view, cursor); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = layoutInflater.inflate(R.layout.word_list_item, null); setView(view, cursor); return view; } public DictionaryAdapter(Context context, Cursor c, boolean autoRequery) { super(context, c, autoRequery); // 通過系統(tǒng)服務(wù)獲得LayoutInflater對象 layoutInflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } }
在編寫DictionaryAdapter類時應(yīng)注意如下3點:
1. 為了將Cursor對象與AutoCompleteTextView組件綁定, DictionaryAdapter類必須從CursorAdapter類繼承。
2. 由于CursorAdapter類中的convertToString方法直接返回了Cursor對象的地址,因此,在DictionaryAdapter類中必須覆蓋convertToString方法,以返回當前選中的單詞。CursorAdapter類中的convertToString方法的源代碼。
public CharSequence convertToString(Cursor cursor) { // 如果cursor不為null,返回Cursor對象的地址(cursor.toString()) return cursor == null ? "" : cursor.toString(); }
覆蓋后的convertToToString方法的源代碼如下:
public CharSequence convertToString(Cursor cursor) { return cursor == null ? "" : cursor.getString(cursor .getColumnIndex("_id")); }
在這里要注意一下,當選中AutoCompleteTextView組件中單詞列表中某一個單詞后,系統(tǒng)會用convertToString方法的返回值來設(shè)置AutoCompleteTextView組件中的文本。因此,必須使用Cursor的getString來獲得相應(yīng)的字段值。
3. 由于將Cursor對象與Adapter綁定時必須要有一個叫“_id”的字段,因此,在本例中將english字段名映射成了“_id”字段。
為了監(jiān)視AutoCompleteTextView組件中的文本輸入情況,需要實現(xiàn)android.text.TextWatcher接口。在該接口中只需要實現(xiàn)afterTextChanged方法即可,代碼如下:
public void afterTextChanged(Editable s) { // 必須將english字段的別名設(shè)為_id Cursor cursor = database.rawQuery( "select english as _id from t_words where english like ?", new String[]{ s.toString() + "%" }); DictionaryAdapter dictionaryAdapter = new DictionaryAdapter(this,cursor, true); // actvWord是在Main類中定義的AutoCompleteTextView類型的變量 actvWord.setAdapter(dictionaryAdapter); }
從上面的代碼中可以看到,在查詢SQL語句中的english字段名的別名是“_id”。
4. 在DictionaryAdapter類中需要使用bindView和newView方法設(shè)置每一個列表項。bindView方法負責設(shè)置已經(jīng)存在的列表項,也就是該列表項已經(jīng)生成了相應(yīng)的組件對象。而newView方法負責設(shè)置新的列表項,在該方法中需要創(chuàng)建一個View對象來顯示當前的列表項。在本例中使用word_list_item.xml布局文件來顯示每一個列表項,代碼如下:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tvWordItem" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="center_vertical" android:paddingLeft="6dip" android:textColor="#000" android:minHeight="?android:attr/listPreferredItemHeight" />
本文介紹了實現(xiàn)基于Android的英文詞典的實現(xiàn)方法。實現(xiàn)英文詞典主要需要解決3個問題:如何將保存英文單詞的SQLite數(shù)據(jù)庫文件隨同apk文件一起發(fā)布;如何打開SD卡中的數(shù)據(jù)庫文件;如何在AutoCompleteTextView組件顯示以輸入字符串開頭的英文單詞列表。在最后仍然要提一句的是在編寫自定義DictionaryAdapter類時一定要覆蓋contertToString方法,以便在用戶選項某一個列表項時在AutoCompleteTextView組件中顯示選中的單詞,而不是Cursor對象地址。
以上就是本文的全部內(nèi)容,希望對大家學習Android軟件編程有所幫助。
相關(guān)文章
Android 封裝Okhttp+Retrofit+RxJava,外加攔截器實例
下面小編就為大家分享一篇Android封裝Okhttp+Retrofit+RxJava,外加攔截器實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01Android開發(fā)實現(xiàn)控件雙擊事件的監(jiān)聽接口封裝類
這篇文章主要介紹了Android開發(fā)實現(xiàn)控件雙擊事件的監(jiān)聽接口封裝類,需要的朋友可以參考下2020-03-03android項目實現(xiàn)帶進度條的系統(tǒng)通知欄消息
本篇文章主要介紹了android項目實現(xiàn)帶進度條的系統(tǒng)通知欄消息,就是實現(xiàn)在通知欄看到下載進度。具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-10-10淺析Android企業(yè)級開發(fā)數(shù)據(jù)綁定技術(shù)
這篇文章通過代碼實例分析了Android企業(yè)級開發(fā)數(shù)據(jù)綁定技術(shù)的應(yīng)用以及相關(guān)的原理知識,跟著小編一起學習參考下吧。2017-12-12