英文词典是手机中经常使用的应用。因此,在本文将结合 Android 来讨论如何实现一个 Android 版的英文词典。实现英文词典的方法很多。在本文使用了 SQLite 数据库来保存英文单词信息。系统通过 SQLite 数据库中保存的单词信息来查找到与指定英文对应的中文信息。当然,实现这样一个英文词典需要解决一系列技术问题。例如,如何将保存英文单词信息的数据库文件随程序( apk 文件)一起发布;发布后如何打开数据库;如何在输入前几个字母后,在 AutoCompleteTextView 组件提示列表中显示以所输入字符串开头的所有单词。在本章将逐渐给出这些问题的详细答案。

实现电子词典要解决的技术问题及初步的解答

在这里将给出实现电子词典需要解决的主要技术问题,并给出这些技术问题的初步答案或提示。关于详细的答案和代码请读者参阅本文后面的内容。
主要技术问题及解答如下:
1. 如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?
解答:可以将dictionary.db文件复制到Eclipse Android工程中的res/raw目录中,如图1所示。所有在res/raw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。

图1
dictionary.db 文件复制到 res/raw 目录中

2. 如何将打开 res/raw 目录中的数据库文件?

解答:在Android 中不能直接打开 res/raw 目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或 SD 卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用 getResources().openRawResource 方法获得 res/raw 目录中资源的 InputStream 对象,然后将该 InputStream 对象中的数据写入其他的目录中相应文件中。在Android SDK 中可以使用 SQLiteDatabase.openOrCreateDatabase 方法来打开任意目录中的 SQLite 数据库文件。

3. 如果在 AutoCompleteTextView 组件中输入两个及以上字母时显示以所输入字符串开头的所有单词列表?

解答: AutoCompleteTextView 所使用的 Adapter 是一个自定义的 Adapter 类,类的结构如下:

public class DictionaryAdapter extends CursorAdapter
{

}

要注意的是,不能将整个数据库中的单词都查出,然后生成一个 Adapter 对象再使用 setAdapter 方法来设置 AutoCompleteTextView 组件的 Adapter 对象。 AutoCompleteTextView 组件不会为我们筛选以某个字符串开头的单词。这些工作需要开发人员通过编码来实现。

基本思路是在 AutoCompleteTextView 类的 afterTextChanged 事件中监视 AutoCompleteTextView 组件中字符的输入情况,每当输入一个字符时就生成一个 Adapter 对象,然后将新生成的 Adapter 对象与 AutoCompleteTextView 关联。显示以输入字符串开头的单词列表的效果如图 2 所示。



图2
显示以输入字符串开头的单词列表

复制并打开保存英文单词的数据库文件

在本文实现的英文词典中使用openDatabase方法来打开数据库文件(该文件在SD卡的dictionary目录中,因此,要想运行本文实现的英文 词典,需要在手机或模拟器中需要安装SD卡)。如果该文件不存在,系统会自动创建/sdcard/dictionary目录,并将res/raw目录中的 dictionary.db文件复制到/sdcard/dictionary目录中。openDatabase方法的实现代码如下:

private SQLiteDatabaseopenDatabase()
{
try
{
// 获得dictionary.db文件的绝对路径
StringdatabaseFilename = DATABASE_PATH + " / " + DATABASE_FILENAME;
Filedir
= new File(DATABASE_PATH);
// 如果/sdcard/dictionary目录中存在,创建这个目录
if ( ! dir.exists())
dir.mkdir();
// 如果在/sdcard/dictionary目录中不存在
// dictionary.db文件,则从res/raw目录中复制这个文件到
// SD卡的目录(/sdcard/dictionary)
if ( ! ( new File(databaseFilename)).exists())
{
// 获得封装dictionary.db文件的InputStream对象
InputStreamis = getResources().openRawResource(R.raw.dictionary);
FileOutputStreamfos
= new FileOutputStream(databaseFilename);
byte []buffer = new byte [ 8192 ];
int count = 0 ;
// 开始复制dictionary.db文件
while ((count = is.read(buffer)) > 0 )
{
fos.write(buffer,
0 ,count);
}

fos.close();
is.close();
}
// 打开/sdcard/dictionary目录中的dictionary.db文件
SQLiteDatabasedatabase = SQLiteDatabase.openOrCreateDatabase(
databaseFilename,
null );
return database;
}
catch (Exceptione)
{
}
return null ;
}

openDatabase 方法中使用了几个常量,这些常量是在程序的主类( Main )中定义的,代码如下:

public class Main extends Activity implements OnClickListener,TextWatcher
{
private final StringDATABASE_PATH = android.os.Environment
.getExternalStorageDirectory().getAbsolutePath()
+ " /dictionary " ;
private final StringDATABASE_FILENAME = " dictionary.db " ;

}


查询单词

英文词典的核心就是查找英文单词的中文意思。在查找中文意思之前,首先需要使用openDatabase方法在Main类的onCreate方法中打开SQLite数据库,代码如下:

database = openDatabase();

其中database是在Main类中定义的SQLiteDatabase类型变量。
然后在查找按钮的单击事件中添加如下的代码来查找英文单词,并显示中文意思。

public void onClick(Viewview)
{
Stringsql
= " selectchinesefromt_wordswhereenglish=? " ;
Cursorcursor
= database.rawQuery(sql, new String[]
{actvWord.getText().toString()});
Stringresult
= " 未找到该单词. " ;
// 如果查找单词,显示其中文信息
if (cursor.getCount() > 0 )
{
// 必须使用moveToFirst方法将记录指针移动到第1条记录的位置
cursor.moveToFirst();
result
= cursor.getString(cursor.getColumnIndex( " chinese " ));
}
// 显示查询结果对话框
new AlertDialog.Builder( this ).setTitle( " 查询结果 " ).setMessage(result)
.setPositiveButton(
" 关闭 " , null ).show();

}

讲到这里我们应该了解一个 dictionary.db 中的 t_words 表的结果,该表只有两个字段: english chinese 。分别表示单词的英文和中文描述。如果要获得单词的中文描述,只需要查找 chinese 字段即可。如 onClick 方法中的代码所示。

查询单词的效果如图 3 所示。


3 查询英文单词

如果显示以输入字符串开头的单词列表

虽然到目前为止,我们的英文词典已经可以正常工作了,但为了方便读者使用,在本节将添加单词输入的自动提示功能。也就是说,如果读者在 AutoCompleteTextView组件中输入单词的前几个字母,该组件就会自动列出数据库中所有以该字符串开头的单词。效果如图2所示。拥有这样 的功能就可以使用户在只知道单词的前几个字母时也可以查找到相应的单词。
由于AutoCompleteTextView组件使用了自定义的Adapter类,下面先给出这个自定义的Adapter类的完整代码。

public class DictionaryAdapter extends CursorAdapter
{
private LayoutInflaterlayoutInflater;
@Override
public CharSequenceconvertToString(Cursorcursor)
{
return cursor == null ? "" :cursor.getString(cursor
.getColumnIndex(
" _id " ));
}
// 用于将_id字段(也就是english字段)的值设置TextView组件的文本
// view参数表示用于显示列表项的TextView组件
private void setView(Viewview,Cursorcursor)
{
TextViewtvWordItem
= (TextView)view;
tvWordItem.setText(cursor.getString(cursor.getColumnIndex(
" _id " )));
}

@Override
public void bindView(Viewview,Contextcontext,Cursorcursor)
{
setView(view,cursor);
}

@Override
public ViewnewView(Contextcontext,Cursorcursor,ViewGroupparent)
{
Viewview
= layoutInflater.inflate(R.layout.word_list_item, null );
setView(view,cursor);
return view;
}
public DictionaryAdapter(Contextcontext,Cursorc, boolean autoRequery)
{
super (context,c,autoRequery);
// 通过系统服务获得LayoutInflater对象

layoutInflater
= (LayoutInflater)context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
}

在编写 DictionaryAdapter 类时应注意如下 3 点:

1. 为了将 Cursor 对象与 AutoCompleteTextView 组件绑定, DictionaryAdapter 类必须从 CursorAdapter 类继承。

2. 由于 CursorAdapter 类中的 convertToString 方法直接返回了 Cursor 对象的地址,因此,在 DictionaryAdapter 类中必须覆盖 convertToString 方法,以返回当前选中的单词。 CursorAdapter 类中的 convertToString 方法的源代码。

public CharSequenceconvertToString(Cursorcursor)
{
// 如果cursor不为null,返回Cursor对象的地址(cursor.toString())
return cursor == null ? "" :cursor.toString();
}

覆盖后的 convertToToString 方法的源代码如下:

public CharSequenceconvertToString(Cursorcursor)
{
return cursor == null ? "" :cursor.getString(cursor
.getColumnIndex(
" _id " ));
}

在这里要注意一下,当选中 AutoCompleteTextView 组件中单词列表中某一个单词后,系统会用 convertToString 方法的返回值来设置 AutoCompleteTextView 组件中的文本。因此,必须使用 Cursor getString 来获得相应的字段值。

3. 由于将 Cursor 对象与 Adapter 绑定时必须要有一个叫“ _id ”的字段,因此,在本例中将 english 字段名映射成了“ _id ”字段。

为了监视 AutoCompleteTextView 组件中的文本输入情况,需要实现 android.text.TextWatcher 接口。在该接口中只需要实现 afterTextChanged 方法即可,代码如下:

public void afterTextChanged(Editables)
{
// 必须将english字段的别名设为_id
Cursorcursor = database.rawQuery(
" selectenglishas_idfromt_wordswhereenglishlike? " ,
new String[]{s.toString() + " % " });
DictionaryAdapterdictionaryAdapter
= new DictionaryAdapter( this ,cursor, true );
// actvWord是在Main类中定义的AutoCompleteTextView类型的变量
actvWord.setAdapter(dictionaryAdapter);
}

从上面的代码中可以看到,在查询 SQL 语句中的 english 字段名的别名是“ _id ”。

4. DictionaryAdapter 类中需要使用 bindView newView 方法设置每一个列表项。 bindView 方法负责设置已经存在的列表项,也就是该列表项已经生成了相应的组件对象。而 newView 方法负责设置新的列表项,在该方法中需要创建一个 View 对象来显示当前的列表项。在本例中使用 word_list_item.xml 布局文件来显示每一个列表项,代码如下:

<? xmlversion="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"
/>

本文介绍了实现基于 Android 的英文词典的实现方法。实现英文词典主要需要解决 3 个问题:如何将保存英文单词的 SQLite 数据库文件随同 apk 文件一起发布;如何打开 SD 卡中的数据库文件;如何在 AutoCompleteTextView 组件显示以输入字符串开头的英文单词列表。在最后仍然要提一句的是在编写自定义 DictionaryAdapter 类时一定要覆盖 contertToString 方法,以便在用户选项某一个列表项时在 AutoCompleteTextView 组件中显示选中的单词,而不是 Cursor 对象地址。

转自:http://blog.csdn.net/chenyongsuda/archive/2010/11/11/6002655.aspx

更多相关文章

  1. WebView 使用Android(安卓)原生ToolBar
  2. Android学习笔记之GridView
  3. Android原理揭秘系列之View、ViewGroup
  4. Android(安卓)Studio环境下连接远程服务器中的sqlserver2012数据
  5. Android中AsyncTask的使用与源码分析+3.0以前的缺陷(并发->逐一)
  6. Android下使用lamemp3库将PCM录音数据压缩为MP3格式
  7. (Android)View.getHeight或getWidth为0时的一些解决方案
  8. Android官方Toolbar自定义高度最靠谱的解决办法
  9. 浅谈Android中的MVP与动态代理的结合

随机推荐

  1. CISSP学习:第12章安全通信与网络攻-击
  2. 让小姐姐在命令行里面性感跳舞
  3. 当年pass到很多扒手的题
  4. 我的第35个代码
  5. js逆向破解百度翻译
  6. Pycharm 被低估了的 10 个快捷键
  7. ||运算你真的了解吗?
  8. 用 Python 自动定时发微博
  9. 还在一行一行的写html,感受痛苦吧
  10. springboot|springboot集成redis缓存