实现基于Android的英文电子词典

简介:
本文为原创,如需转载,请注明作者和出处,谢谢!  

        英文词典是手机中经常使用的应用。因此,在本文将结合 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方法的实现代码如下:
复制代码
ExpandedBlockStart.gif 代码
     private  SQLiteDatabase openDatabase()
    {
        
try
        {
            
//  获得dictionary.db文件的绝对路径
            String databaseFilename  =  DATABASE_PATH  +   " / "   +  DATABASE_FILENAME;
            File dir 
=   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对象
                InputStream is  =  getResources().openRawResource(R.raw.dictionary);
                FileOutputStream fos 
=   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文件
            SQLiteDatabase database  =  SQLiteDatabase.openOrCreateDatabase(
                    databaseFilename, 
null );
            
return  database;
        }
        
catch  (Exception e)
        {
        }
        
return   null ;
    }
复制代码

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

复制代码
ExpandedBlockStart.gif 代码
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数据库,代码如下:

database = openDatabase();

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

复制代码
ExpandedBlockStart.gif 代码
     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 " ));
        }
        
//   显示查询结果对话框
         new  AlertDialog.Builder( this ).setTitle( " 查询结果 " ).setMessage(result)
                .setPositiveButton(
" 关闭 " null ).show();

    }
复制代码


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



                                       图查询英文单词

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

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

复制代码
ExpandedBlockStart.gif 代码
     public   class  DictionaryAdapter  extends  CursorAdapter
    {
        
private  LayoutInflater layoutInflater;
        @Override
        
public  CharSequence convertToString(Cursor cursor)
        {
            
return  cursor  ==   null   ?   ""  : cursor.getString(cursor
                    .getColumnIndex(
" _id " ));
        }
        
//   用于将_id字段(也就是english字段)的值设置TextView组件的文本
        
//   view参数表示用于显示列表项的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);
            
//   通过系统服务获得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  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组件中单词列表中某一个单词后,系统会用convertToString方法的返回值来设置AutoCompleteTextView组件中的文本。因此,必须使用CursorgetString来获得相应的字段值。

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

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

复制代码
ExpandedBlockStart.gif 代码
public   void  afterTextChanged(Editable s)
{
     
//   必须将english字段的别名设为_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类中需要使用 bindViewnewView方法设置每一个列表项。 bindView方法负责设置已经存在的列表项,也就是该列表项已经生成了相应的组件对象。而 newView方法负责设置新的列表项,在该方法中需要创建一个 View对象来显示当前的列表项。在本例中使用 word_list_item.xml布局文件来显示每一个列表项,代码如下:

 

复制代码
ExpandedBlockStart.gif 代码
<? 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"
/>
复制代码

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

本文转自银河使者博客园博客,原文链接http://www.cnblogs.com/nokiaguy/archive/2010/07/31/1789218.html如需转载请自行联系原作者


银河使者


相关文章
|
3月前
|
数据采集 小程序 数据可视化
智慧校园电子班牌管理系统源码 Java Android原生
家长通过家长小程序端随时了解孩子在校的情况,实时接收学生的出勤情况,学生到校、离校时间。随时了解学生在校的表现、学生成绩排名,及时与教师沟通,关注孩子的健康成长。
30 0
智慧校园电子班牌管理系统源码 Java Android原生
|
Android开发
flutter中实现仿Android端的onResume和onPause方法
flutter中实现仿Android端的onResume和onPause方法
|
1月前
|
定位技术 API 数据库
基于Android的在线移动电子导航系统的研究与实现(论文+源码)_kaic
基于Android的在线移动电子导航系统的研究与实现(论文+源码)_kaic
|
2月前
|
小程序 JavaScript Java
android电子班牌人脸识别系统源码
智慧校园云平台全套源码包含:电子班牌管理系统、成绩管理系统、考勤人脸刷卡管理系统、综合素养评价系统、请假管理系统、电子班牌发布系统、校务管理系统、小程序移动端、教师后台管理系统、SaaS运营云平台。
34 1
|
2月前
|
小程序 Java 数据挖掘
Java校园智慧管理云平台源码 小程序+android电子班牌系统
智慧校园技术架构 ❀后端:Java ❀框架:springboot ❀前端页面:vue +element-ui ❀小程序:小程序原生开发 ❀电子班牌:Java Android
36 0
|
4月前
|
小程序 JavaScript Java
智慧校园系统源码,android电子班牌人脸识别系统
智慧校园系统源码,android电子班牌人脸识别系统
46 0
|
Android开发 容器
Android实现面包屑效果,支持Fragment联动
Android实现面包屑效果,支持Fragment联动
|
Android开发
Android实现连线题效果
Android实现连线题效果
|
Android开发
Android实现调用系统相机录像及实现录音
Android实现调用系统相机录像及实现录音
582 0
|
移动开发 JavaScript Android开发
通过howler.js实现在Android下的微信浏览器自动播放音频
通过howler.js实现在Android下的微信浏览器自动播放音频
403 0
通过howler.js实现在Android下的微信浏览器自动播放音频