示例图片二

和我一起开发Android应用(三)——“悦词-i背单词”词典功能实现,android-i

2019-02-01 09:42:41 环亚娱乐 已读

和我一起开发Android应用(三)——“悦词-i背单词”词典功能实现,android-i

  接上一讲。本节我们把词典功能基本实现,首先上一个效果图,我发现大家比较关心界面方面的东西,我之前写的一个关于QQ界面的项目就很受欢迎,当然我现在能写出远比那个好看的界面。但是我想一个应用最核心的东西不完全在界面,一个好的创意,一个好的后台服务才是成功的关键,这也是我不断学习的方向。

  另外我发现在百度搜“悦词背单词91”搜索结果全是我在博客园的博文了。。。所以我把这个项目在91应用市场的下载地址粘上来吧,十分欢迎大家试用一下,有什么改进的意见请写在下面的评论里!地址:http://apk.91.com/Soft/Android/com.carlos.yueci-4.html

 

  今天我们就实现这个界面,一个能查词的词典。

  

  为了明确思路,把上一节的项目功能分析拷贝过来:

 功能分析:

功能1、查单词。

  实现方法:金山词霸开放平台提供了一个开放API,通过Http访问金山词霸API提供的URL,可以获得一个XML文档,这个文档就包含了要查询的单词的释义、例句、音标、声音的地址。通过解析该XML就可以获得单词的所有信息。

  所用到的技术:

    1)Http访问网络,并下载网络文件

    2)对SD卡进行操作,从SD卡(这里的SD卡是指手机默认的存储卡,因为有些手机既能能插SD卡又有内部存储,这里不涉及这个问题)中读取文件,和把从网络下载的文件存进SD卡。

    3)解析XML文件

    4)播放音乐(这个我后来封装成了一个类,专门从网络上查询某个单词,解析XML文件,并且将下载的Mp3文件存在SD卡中,然后播放该Mp3文件)

    5)数据库,这里涉及到第一个数据库,每查找一个单词之后,就会将该单词和释义存储到一个SQLite数据库中。这样一来,下一次查找这个单词时,先访问数据库,看看数据库中有没有这个单词,若有,就不用访问网络了。

   根据上面的分析,可见我们已经实现了Http网络模块,XML文件解析,还有三个内容,我们先实现这三个功能,然后再把UI搭建起来。

  (一)后台功能实现

    一、对SD进行操作。FileUtils类,一个专门用于实现讲输入流写入文件,从文件中获得输入流的类,当我们从网上搜索一个单词后,会把它对应的音频Mp3存储在本地的一个文件夹,这样当我们再查这个单词或者在背单词时遇到这个单词时,就不用再访问网络了。

package com.carlos.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import android.os.Environment;

public class FileUtils {
    private String SDPATH;  

    public FileUtils(){
        SDPATH=Environment.getExternalStorageDirectory()+"/";
        
        //System.out.println(Environment.getExternalStorageDirectory().getAbsolutePath());
    }
    
    //创建文件,一定不会返回空
    /**
     * 
     * @param path 直接创建文件即可,无需考虑文件夹有没有创建,若文件已存在返回null
     * @param fileName
     * @return
     */
    public File createSDFile(String path,String fileName){
        File file=null;
        createSDDir(path);
        try{
        file=new File(SDPATH+path+fileName);
        if(file.exists() && file.isFile()){
            return null;
        }
        file.createNewFile();  //创建文件
        
        }catch(Exception e){
            e.printStackTrace();
        }
        return file;
    }
    
    //创建目录,如果存在同名文件夹则返回该文件夹,否则创建文件
    public File createSDDir(String dirName){
        File dir=new File(SDPATH+dirName);
        if(dir.exists() && dir.isDirectory()){
            return dir;
        }
        dir.mkdirs();  //可创建多级文件夹
        return dir;
    }
    
    
    //这里写相对目录
    public ArrayList<String> listContentsOfFile(String path){
        ArrayList<String> list=new ArrayList<String>();
        File file=new File(SDPATH+path);
        File[] fileList=file.listFiles();
        if(fileList==null)
            return list;
        for(int i=0; i<fileList.length;i++){
            System.out.println(fileList[i].getName());
        }
        return list;
    }
    
    //判断SD卡文件夹是否存在
    public boolean isFileExist(String path,String fileName){
        File file=new File(SDPATH+path+fileName);
        return file.exists();
    }
    
    //获得文件输入流
    public InputStream getInputStreamFromFile(String path,String fileName){
        InputStream input=null;
        File file=new File(SDPATH+path+fileName);
        if(file.exists()==false)
            return null;
        try {
            input=new FileInputStream(file);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch bloc
            e.printStackTrace();
            return null;
        }
        
        return input;
    }
    
    
    /**
     * 
     * @param in
     * @param path  文件存储的相对路径
     * @param fileName
     * @return
     */
    public boolean saveInputStreamToFile(InputStream in, String path,String fileName ){
        File file=createSDFile(path,fileName); //相对路径即可
        int length=0;
        if(file==null)
            return true;  //其实这里的情况是文件已存在
        byte[] buffer=new byte[1024];
        FileOutputStream fOut=null;
        try {
            fOut=new FileOutputStream(file);
        
            while((length=in.read(buffer))!=-1){          //要利用read返回的实际成功读取的字节数,将buffer写入文件,否则将会出现错误的字节
                fOut.write(buffer, 0, length);
            }
            
        } catch (Exception e) {
            // TODO Auto-generated catch block        
            e.printStackTrace();
            return false;    
        }finally{
            try {
                fOut.close();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }    
        }
        return true;
    }
    
    
    public String getSDRootPath(){
        return Environment.getExternalStorageDirectory().getAbsolutePath()+"/";
    }
    
    public String getSDPATH() {
        return SDPATH;
    }

    public void setSDPATH(String sDPATH) {
        SDPATH = sDPATH;
    }
    
    
    
    

}

各个函数的功能已经有说明,这个属于一个工具类,可无需改动使用。

 

    二、数据库,用于存放所查的单词的单词、音标、释义、例句

1、首先需创建一个DataBaseHelper类,继承SQLiteOpenHelper类:

package com.carlos.database;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DataBaseHelperDict extends SQLiteOpenHelper{

    public Context mContext=null;
    public String tableName=null;
    public static int VERSION=1;
    public DataBaseHelperDict(Context context, String name, CursorFactory factory,
            int version) {
        super(context, name, factory, version);
        // TODO Auto-generated constructor stub
        mContext=context;
        tableName=name;
    }   
    
    public DataBaseHelperDict(Context context, String name, CursorFactory factory){
        this(context,name,factory,VERSION);
        mContext=context;
        tableName=name;
    }
    
    public DataBaseHelperDict(Context context, String name){
        this(context,name,null);
        mContext=context;
        tableName=name;
    };


    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        db.execSQL("create table dict(word text,pse text,prone text,psa text,prona text," +
                "interpret text, sentorig text, senttrans text)");
        
    }

    @Override
    public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
        // TODO Auto-generated method stub
        
    }
    
    

}

  这是一个非常简单的类,在onCreate方法中我们需要用到类似JDBC的语言创建一个表table

    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        db.execSQL("create table dict(word text,pse text,prone text,psa text,prona text," +
                "interpret text, sentorig text, senttrans text)");
        
    }

其中word 单词,pse 英式音标,prone 英式发音地址,psa 美式音标,prona 美式发音地址,interpret 翻译, sentorig 利用英文, senttrans 例句中文  

这8项是这个表的8列,用于存储一个单词的所有信息。

 

 那么接下来的问题便是,有了这个数据库我们怎么操作它呢?为此我封装了一个词典类Dict,这个类具有和词典一样的功能:在词典中查找一个单词,查找一个单词的翻译,或例句,从网络上下载某个单词的信息,将某个单词添加到词典中。一些细节的说明在代码中有注释

package com.carlos.wordcontainer;

import java.io.BufferedReader;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.ArrayList;

import java.util.LinkedList;

import org.xml.sax.InputSource; 

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

import com.carlos.database.DataBaseHelperDict;
import com.carlos.internet.NetOperator;
import com.carlos.text_parser.JinShanContentHandler;
import com.carlos.text_parser.XMLParser;
import com.carlos.utils.FileUtils;

public class Dict {   
    public Context context=null; 
    public String tableName=null;
    private DataBaseHelperDict dbHelper=null;
    private SQLiteDatabase dbR=null,dbW=null;
    

    public Dict(Context context,String tableName){
        this.context=context;
        this.tableName=tableName;
        dbHelper=new DataBaseHelperDict(context, tableName);     //这里要用到前面的DataBaseHelper类,在Dict的构造方法中实例化该类,
//并且调用下面两个方法获得dbR和dbW,用于完成对数据库的增删改查操作。
//这里吧dbR dbW作为成员变量目的是避免反复实例化dbR dbW造成数据库指针泄露。
dbR=dbHelper.getReadableDatabase(); dbW=dbHelper.getWritableDatabase(); } @Override protected void finalize() throws Throwable { //在该对象销毁时,释放dbR和dbW // TODO Auto-generated method stub dbR.close(); dbW.close(); dbHelper.close(); super.finalize(); }
//将包含单词信息的WordValue对象添加进数据库,这里使用了dbW的insert方法,需要创建一个ContentValue对象存放键值对 public void insertWordToDict(WordValue w, boolean isOverWrite){ if(w==null){ //避免空指针异常 return; } Cursor cursor=null; try{ ContentValues values=new ContentValues(); values.put("word",w.getWord() ); values.put("pse", w.getPsE()); values.put("prone",w.getPronE()); values.put("psa", w.getPsA()); values.put("prona", w.getPronA()); values.put("interpret",w.getInterpret()); values.put("sentorig", w.getSentOrig()); values.put("senttrans", w.getSentTrans()); cursor=dbR.query(tableName, new String[]{"word"}, "word=?", new String[]{w.getWord()}, null, null, null); if(cursor.getCount()>0){ if(isOverWrite==false)//首先看看数据库中有没有这个单词,若词典库中已经有了这一个单词,所以不再操作 return; else{ //执行更新操作 dbW.update(tableName, values, "word=?",new String[]{ w.getWord()}); } }else{ dbW.insert(tableName, null, values); //这里可能会发生空指针异常,到时候考虑 } }catch(Exception e){ }finally{ if(cursor!=null) cursor.close(); } }
//判断数据库中是否存在某个单词 public boolean isWordExist(String word){ Cursor cursor=null; try{ cursor=dbR.query(tableName, new String[]{"word"}, "word=?", new String[]{word}, null, null, null); if(cursor.getCount()>0){ cursor.close(); return true; }else{ cursor.close(); return false; } }finally{ if(cursor!=null) cursor.close(); } }
//从单词库中获得某个单词的信息,如果词库中没有改单词,那么返回null public WordValue getWordFromDict(String searchedWord){ WordValue w=new WordValue();//预防空指针异常 // db.execSQL("create table dict(word text,pse text,prone text,psa text,prona text," + // "interpret text, sentorig text, senttrans text)"); String[] columns=new String[]{"word", "pse","prone","psa","prona","interpret","sentorig","senttrans"}; String[] strArray=new String[8]; Cursor cursor=dbR.query(tableName, columns, "word=?", new String[]{searchedWord}, null, null, null); while(cursor.moveToNext()){ for(int i=0;i<strArray.length;i++){ strArray[i]=cursor.getString(cursor.getColumnIndex(columns[i])); } w=new WordValue(strArray[0],strArray[1],strArray[2],strArray[3],strArray[4],strArray[5],strArray[6],strArray[7]); } cursor.close(); return w; }
//从网络查找某个单词,并且返回一个含有单词信息的WordValue对象,这个方法在第二讲的最后提过 public WordValue getWordFromInternet(String searchedWord){ WordValue wordValue=null; String tempWord=searchedWord; if(tempWord==null&& tempWord.equals("")) return null; char[] array=tempWord.toCharArray(); if(array[0]>256) //是中文,或其他语言的的简略判断 tempWord="_"+URLEncoder.encode(tempWord); InputStream in=null; String str=null; try{ String tempUrl=NetOperator.iCiBaURL1+tempWord+NetOperator.iCiBaURL2; in=NetOperator.getInputStreamByUrl(tempUrl); if(in!=null){ new FileUtils().saveInputStreamToFile(in, "", "gfdgf.txt"); XMLParser xmlParser=new XMLParser(); InputStreamReader reader=new InputStreamReader(in,"utf-8"); JinShanContentHandler contentHandler=new JinShanContentHandler(); xmlParser.parseJinShanXml(contentHandler, new InputSource(reader)); wordValue=contentHandler.getWordValue(); wordValue.setWord(searchedWord); } }catch(Exception e){ e.printStackTrace(); } return wordValue; }

//以下几个方法都是获得某个单词的某一项信息,基本的思路还是先获得全部信息WordValue然后调用WordValue的get方法获得具体的信息。 //获取发音文件地址 public String getPronEngUrl(String searchedWord){ Cursor cursor=dbR.query(tableName, new String[]{"prone"}, "word=?", new String[]{searchedWord}, null, null, null); if(cursor.moveToNext()==false){ cursor.close(); return null; } String str=cursor.getString(cursor.getColumnIndex("prone")); cursor.close(); return str; } public String getPronUSAUrl(String searchedWord){ Cursor cursor=dbR.query(tableName, new String[]{"prona"}, "word=?", new String[]{searchedWord}, null, null, null); if(cursor.moveToNext()==false){ cursor.close(); return null; } String str=cursor.getString(cursor.getColumnIndex("prona")); cursor.close(); return str; } //获取音标 public String getPsEng(String searchedWord){ Cursor cursor=dbR.query(tableName, new String[]{"pse"}, "word=?", new String[]{searchedWord}, null, null, null); if(cursor.moveToNext()==false){ cursor.close(); return null; } String str=cursor.getString(cursor.getColumnIndex("pse")); cursor.close(); return str; } public String getPsUSA(String searchedWord){ Cursor cursor=dbR.query(tableName, new String[]{"psa"}, "word=?", new String[]{searchedWord}, null, null, null); if(cursor.moveToNext()==false){ cursor.close(); return null; } String str=cursor.getString(cursor.getColumnIndex("psa")); cursor.close(); return str; } /** * 若没有句子那么返回的链表的长度为0,若单词不存在那么直接返回null,所以最好对null和长度同时检验 * @param searchedWord * @return */ public String getInterpret(String searchedWord){ Cursor cursor=dbR.query(tableName, new String[]{"interpret"}, "word=?", new String[]{searchedWord}, null, null, null); if(cursor.moveToNext()==false){ cursor.close(); return null; } String str=cursor.getString(cursor.getColumnIndex("interpret")); cursor.close(); return str; } }

有了这个类以后大家可能会有一个比较明确的思路了,在接下来将UI时Activity中会实例化一个Dict对象,直接调用它的某些方法完成操作。

 

    三、音频播放

  当我们查到一个单词时,可能想听一听这个单词的发音,这时就需要根据数据库中prone/prona这一列的音频地址,从网络上获得音频输入流下载到SD卡,然后调用MediaPlayer播放音乐,这是一个一系列的动作,再后面背单词时因为要听单词的发音,会更多的用到这个操作,为此我封装了一个方法,专门完成这组操作。

package com.carlos.music;

import java.io.InputStream;
import java.io.InputStreamReader;

import org.xml.sax.InputSource;

import com.carlos.internet.NetOperator;
import com.carlos.text_parser.JinShanContentHandler;
import com.carlos.text_parser.XMLParser;
import com.carlos.utils.FileUtils;
import com.carlos.wordcontainer.Dict;
import com.carlos.wordcontainer.WordValue;
import com.carlos.yueci.ReciteActivity;

import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;

public class Mp3Player {
    public final static String MUSIC_ENG_RELATIVE_PATH="yueci/sounds/sounds_EN/";
    public final static String MUSIC_USA_RELATIVE_PATH="yueci/sounds/sounds_US/";
    public final static int ENGLISH_ACCENT=0;
    public final static int USA_ACCENT=1;
     
    public Context context=null;
    public String tableName=null;  
    public MediaPlayer mediaPlayer=null;
    FileUtils fileU=null;
    Dict dict=null;
    public  boolean isMusicPermitted=true;     //用于对是否播放音乐进行保护性设置,当该变量为false时,可以阻止一次音乐播放
    
    public Mp3Player(Context context,String tableName){
        this.context=context;
        this.tableName=tableName;
        fileU=new FileUtils();
        dict=new Dict(context,tableName);
        isMusicPermitted=true;
        
    }
    /**
     * 首先先看一下SD卡上有没有,若有则播放,没有执行下一步
     * 看一下dict表中有没有单词的记录,若有,看一下发音字段是不是有美式发音或英式发音,若无则退出
     * 若没有字段记录,访问网络下载Mp3然后播放
     * 一个Activity中一般只能有一个Voice成员变量,对应的也就只有一个MediaPlayer对象,这样才能对播放
     * 状态进行有效控制
     * 该方法原则上只能在线程中调用     
     * @param word
     * @param accent
     */
    public void playMusicByWord(String word , int accent,boolean isAllowedToUseInternet, boolean isPlayRightNow){
        if(word==null || word.length()<=0)
            return;
        char[] wordArray=word.toCharArray();
        char initialCharacter=wordArray[0];
        
        String path=null;
        String pronUrl=null;
        WordValue w=null;
        
        if(accent==ENGLISH_ACCENT){
            path=MUSIC_ENG_RELATIVE_PATH;
        }else{
            path=MUSIC_USA_RELATIVE_PATH;  
        }
        
        if(fileU.isFileExist(path+initialCharacter+"/","-$-"+word+".mp3")==false){
            if(isAllowedToUseInternet==false)
                return;
            //为了避免多次多个线程同时访问网络下载同一个文件,这里加了这么一个控制变量
            
            if(dict.isWordExist(word)==false){  //数据库中没有单词记录,从网络上进行同步                
                if((w=dict.getWordFromInternet(word))==null){
                    return;
                }
                dict.insertWordToDict(w, true);
            }//能走到这一步说明从网上同步成功,数据库中一定存在单词记录
            
            if(accent==ENGLISH_ACCENT){  
                pronUrl=dict.getPronEngUrl(word);
            }else{
                pronUrl=dict.getPronUSAUrl(word);
            }
            if(pronUrl==null ||pronUrl=="null"||pronUrl.length()<=0)
                return;    //这说明网络上也没有对应发音,故退出
            //得到了Mp3地址后下载到文件夹中然后进行播放
            
            InputStream in=null;
            in = NetOperator.getInputStreamByUrl(pronUrl);
            if(in==null)
                return;
            if(fileU.saveInputStreamToFile(in, path+initialCharacter+"/","-$-"+word+".mp3")==false)
                return;
        }
        //走到这里说明文件夹里一定有响应的音乐文件,故在这里播放
        if(isPlayRightNow==false)
            return;
    
        /**  
         * 这个方法存在缺点,可能因为同时new 了多个MediaPlayer对象,导致start方法失效,
         * 因此解决的方法是,使用同一个MediaPlayer对象,若一次播放时发现对象非空,那么先
         * 调用release()方法释放资源,再重新create
         */
        
           
        if(isMusicPermitted==false){
            return;
        }

        
        try{
            if(mediaPlayer!=null){  
                if(mediaPlayer.isPlaying())
                    mediaPlayer.stop();
                mediaPlayer.release();
                mediaPlayer=null;     //为了防止mediaPlayer多次调用stop release,这里置空还是有必要
            }
            mediaPlayer=MediaPlayer.create(context, Uri.parse("file://"+fileU.getSDRootPath()
                    +path+initialCharacter+"/-$-"+word+".mp3"));
            mediaPlayer.start();

        }catch(Exception e){
            mediaPlayer.release();
            e.printStackTrace();
        }

    }
    
    

}

 

public void playMusicByWord(String word , int accent,boolean isAllowedToUseInternet, boolean isPlayRightNow){}

这个方法的基本逻辑:
根据接受的单词word,先看“词典”(数据库)中有没有该单词记录,若没有,先调用dict的getWordFromInternet()获取单词信息存储进数据库“词典”中,然后根据对应的口音accent,获得prone或prona的地址,然后访问网络,讲Mp3下载到本地,然后调用MediaPlayer对象播放音乐。

需要注意的几点:
  形参中isAllowedToUseInternet 是用于控制是否允许访问网络,添加这个控制项是因为,我们在播放音乐时有时候不想让该方法访问网络,因为过多的县城访问网络可能会造成同时下载同一个音频,会造成线程阻塞或者下载的文件数据损坏。
isPlayeRightNow 是用于控制是否立即播放该MP3,因为在之后实现背单词功能时有时只需要把MP3文件下载下来,而并不需要立刻播放,例如背单词时给你中文意思和英文选项,此时就不能立即播放音乐,否则就知道选项是什么了。
注意到还有一个isMusicPermitted 参量这是个静态成员变量,这个参量是用来阻止一次播放的,比如我们背单词时,突然不想背了退出,此时可能单词的音频正好要播放,这时需要把isMusicPermitted置为false,否则会出现退出后仍播放单词发音的现象。


OK,添加了上述三个支持功能我们终于可以进行最后的进击————搭建UI界面了。
这里插一句题外话,虽然在写教程时我是先实现了上述五个功能然后再搭的界面,但实际开发时这两个工作是同时进行的,我喜欢先把简单的UI搭出来,然后再慢慢实现各个按钮的功能,遇到需要的后台支持再实现它,很难说这两种方法哪个效率高些,我觉得还是先搭一个粗略的框架,然后实现后台功能,然后再回过头来完善UI和后台功能,这其中要经过n次调试。 我这里之所以先给出了完整的后台功能是因为应用已经写完了,我想让整个开发过程的思路更清晰一些。


(二)UI搭建

一、布局文件:先给出一个总的布局文件然后我根据图片分析。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#E5E6E0" >
    
    <RelativeLayout
        android:id="@+id/edit_text_dict_search_bar"  
                android:layout_width="match_parent"
                android:layout_height="42dp"
                    android:layout_alignParentTop="true"
                android:background="#2C2C2C" 
                android:focusable="true"
                android:focusableInTouchMode="true"
                  >
                 
                <ImageButton
                    android:id="@+id/image_btn_dict_back_to_general" 
                    android:layout_width="50dp"
                        android:layout_height="match_parent"
                        android:layout_marginTop="1dp"
                        android:layout_marginBottom="1dp"
                        android:layout_marginLeft="1dp"
                        android:layout_alignParentLeft="true"
                        android:layout_weight="5"
                        android:background="@android:color/transparent"
                        android:src="@drawable/btn_back_blue"/>  
                        
                <ImageButton
                        android:id="@+id/image_btn_dict_search"
                        android:layout_width="50dp"
                        android:layout_height="match_parent"
                        android:layout_alignParentRight="true"
                        android:background="@android:color/transparent"
                        android:src="@android:drawable/ic_menu_search" />

                    <EditText
                        android:paddingLeft="10dp"
                        android:id="@+id/edit_text_dict"
                        android:layout_toRightOf="@id/image_btn_dict_back_to_general"
                        android:layout_toLeftOf="@id/image_btn_dict_search" 
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/edit_back"
                    android:inputType="text"     
                    android:maxLines="1"
                    android:gravity="center_vertical"
                    android:hint="请在此输入单词"
                    android:textColor="#FCFDFE"
                    android:imeOptions="actionSearch"
                     />
                    
                    
                    
                    <ImageButton 
                        android:id="@+id/image_btn_dict_delete_all"
                        android:layout_width="35dp"
                        android:layout_height="match_parent"
                        android:layout_marginTop="5dp"
                        android:layout_marginBottom="5dp"
                        android:layout_toLeftOf="@id/image_btn_dict_search"   
                        android:scaleType="fitXY"
                        android:src="@drawable/delete_all"
                        android:background="@android:color/transparent"/>
                    

                    
            
    </RelativeLayout>
    

    
    <TextView 
        android:id="@+id/text_dict_word"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="fabulous"
        android:gravity="bottom"
        android:textColor="#3B3C3D"
        android:textStyle="bold"
        android:textSize="24sp"
        android:layout_below="@id/edit_text_dict_search_bar"
        android:layout_marginTop="36dp"
        android:layout_marginLeft="22dp"
        android:layout_marginRight="22dp"
        android:layout_marginBottom="3dp"/>
    
    <ImageButton 
        android:id="@+id/image_btn_dict_add_to_wordlist"
        android:layout_height="30dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="30dp"
        android:layout_width="30dp"
        android:layout_alignParentRight="true"
        android:layout_alignTop="@id/text_dict_word"
        android:src="@drawable/add_danciben"
        android:background="@android:color/transparent"
        android:scaleType="fitXY"/>


    
    <RelativeLayout
        android:id="@+id/phonetic_bar" 
        android:layout_width="match_parent"
        android:layout_marginLeft="22dp"
        android:layout_height="40dp"
        android:layout_below="@id/text_dict_word">
        <ImageButton 
            android:id="@+id/image_btn_dict_horn_accent_eng"
            android:layout_height="match_parent"
            android:layout_marginTop="7dp"
            android:layout_marginBottom="7dp"
            android:layout_width="30dp"
            android:background="@android:color/transparent"
            android:src="@drawable/horn_dict"
            android:scaleType="fitCenter"
            />
        <TextView 
            android:id="@+id/text_dict_phosymbol_eng"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:text="英[fanted]"
            android:gravity="center_vertical"
            android:textColor="#6C6C6C"
            android:textSize="14sp"
            android:layout_toRightOf="@id/image_btn_dict_horn_accent_eng"/>
        <TextView 
            android:id="@+id/text_dict_phosymbol_divider"
            android:layout_height="match_parent"
            android:layout_width="50dp"
            android:text="/"
            android:gravity="center"
            android:textColor="#6C6C6C"
            android:textSize="14sp"
            android:layout_toRightOf="@id/text_dict_phosymbol_eng"/>
        
        <ImageButton 
            android:id="@+id/image_btn_dict_horn_accent_usa"
            android:layout_height="match_parent"
            android:layout_marginTop="7dp"
            android:layout_marginBottom="7dp"
            android:layout_width="30dp"
            android:background="@android:color/transparent"
            android:src="@drawable/horn_dict"
            android:scaleType="fitCenter"
            android:layout_toRightOf="@id/text_dict_phosymbol_divider"
            />
        
        <TextView 
            android:id="@+id/text_dict_phosymbol_usa"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:text="美[fan'ted]"
            android:gravity="center_vertical"
            android:textColor="#6C6C6C"
            android:textSize="14sp"
            android:layout_toRightOf="@id/image_btn_dict_horn_accent_usa"/>
        
        
    </RelativeLayout>
    
    <LinearLayout 
        android:id="@+id/dict_interpret_divider"
        android:layout_height="20dp"
        android:layout_width="match_parent"
        android:layout_marginLeft="10dp"
        android:layout_below="@id/phonetic_bar"
        android:orientation="horizontal">
        <ImageView 
            android:layout_width="30dp"
            android:layout_height="match_parent"
            android:src="@drawable/right_cursor"/>
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="基本释义"
            android:textSize="14sp"
            android:textColor="#00A2DC"
            android:gravity="center_vertical"/>
        
    </LinearLayout>
    
      
    <TextView 
        android:id="@+id/text_dict_interpret"
        android:layout_below="@id/dict_interpret_divider"
        android:layout_width="match_parent"
        android:layout_margin="10dp"
        android:layout_height="80dp"
        android:background="@drawable/layer_list_dict_item_back"
        android:padding="12dp"
        android:text="不切实际的
srge了然于心fsfg"
        android:textSize="14sp"
        android:textColor="#3C3C3C"
        android:lineSpacingMultiplier="1.2"/>
    
    <LinearLayout 
        android:id="@+id/dict_sentence_divider"
        android:layout_height="20dp"
        android:layout_width="match_parent"
        android:layout_marginLeft="10dp"
        android:layout_below="@id/text_dict_interpret"
        android:orientation="horizontal">
        <LinearLayout 
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="2"
            >
            <ImageView 
                android:layout_width="30dp"
                android:layout_height="match_parent"
                android:src="@drawable/right_cursor"/>
            <TextView 
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:text="例句"
                android:textSize="14sp"
                android:textColor="#00A2DC"
                android:gravity="center_vertical"/>
            
        </LinearLayout>
        
        <RelativeLayout 
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:layout_weight="1">
            
            <ImageView
                android:id="@+id/dict_jinshan_ico" 
                android:layout_height="match_parent"
                android:layout_width="30dp"
                android:layout_alignParentRight="true"
                android:layout_marginRight="15dp"
                android:src="@drawable/jinshan_ico"/>
            <TextView 
                android:layout_height="match_parent"
                android:layout_width="wrap_content"
                android:gravity="bottom"
                android:layout_toLeftOf="@id/dict_jinshan_ico"
                android:text="supported by iCIBA"
                android:textColor="#6C6C6C"
                android:textSize="10sp"/>
            
        </RelativeLayout>
        
        
    </LinearLayout>
    
   
    <ListView 
        android:id="@+id/listview_dict_sentence"
        android:layout_below="@id/dict_sentence_divider"
        android:layout_width="match_parent"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:padding="12dp"
         android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@drawable/layer_list_dict_item_back"
        android:divider="#8C8C8C"
        android:dividerHeight="0px"
        >
        
    </ListView>
    

</RelativeLayout>

是不是有点晕呢?我把布局分成几块就懂了。

Part One:

这是顶部的横条,这是一个RelativeLayout,里面有以后Back 按钮, 搜索按钮, 删除EditText内容的按钮,还有一个EditText,对应的代码如下:
    <RelativeLayout
        android:id="@+id/edit_text_dict_search_bar"  
                android:layout_width="match_parent"
                android:layout_height="42dp"
                    android:layout_alignParentTop="true"
                android:background="#2C2C2C" 
                android:focusable="true"
                android:focusableInTouchMode="true"
                  >
                 
                <ImageButton
                    android:id="@+id/image_btn_dict_back_to_general" 
                    android:layout_width="50dp"
                        android:layout_height="match_parent"
                        android:layout_marginTop="1dp"
                        android:layout_marginBottom="1dp"
                        android:layout_marginLeft="1dp"
                        android:layout_alignParentLeft="true"
                        android:layout_weight="5"
                        android:background="@android:color/transparent"
                        android:src="@drawable/btn_back_blue"/>  
                        
                <ImageButton
                        android:id="@+id/image_btn_dict_search"
                        android:layout_width="50dp"
                        android:layout_height="match_parent"
                        android:layout_alignParentRight="true"
                        android:background="@android:color/transparent"
                        android:src="@android:drawable/ic_menu_search" />

                    <EditText
                        android:paddingLeft="10dp"
                        android:id="@+id/edit_text_dict"
                        android:layout_toRightOf="@id/image_btn_dict_back_to_general"
                        android:layout_toLeftOf="@id/image_btn_dict_search" 
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/edit_back"
                    android:inputType="text"     
                    android:maxLines="1"
                    android:gravity="center_vertical"
                    android:hint="请在此输入单词"
                    android:textColor="#FCFDFE"
                    android:imeOptions="actionSearch"
                     />
                    
                    
                    
                    <ImageButton 
                        android:id="@+id/image_btn_dict_delete_all"
                        android:layout_width="35dp"
                        android:layout_height="match_parent"
                        android:layout_marginTop="5dp"
                        android:layout_marginBottom="5dp"
                        android:layout_toLeftOf="@id/image_btn_dict_search"   
                        android:scaleType="fitXY"
                        android:src="@drawable/delete_all"
                        android:background="@android:color/transparent"/>
                    

                    
            
    </RelativeLayout>

 

这一块就是TextView  ImageButton(加入单词本)进行的一个Relative布局,没什么特别之处:布局代码如下
<TextView 
        android:id="@+id/text_dict_word"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="fabulous"
        android:gravity="bottom"
        android:textColor="#3B3C3D"
        android:textStyle="bold"
        android:textSize="24sp"
        android:layout_below="@id/edit_text_dict_search_bar"
        android:layout_marginTop="36dp"
        android:layout_marginLeft="22dp"
        android:layout_marginRight="22dp"
        android:layout_marginBottom="3dp"/>
    
    <ImageButton 
        android:id="@+id/image_btn_dict_add_to_wordlist"
        android:layout_height="30dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="30dp"
        android:layout_width="30dp"
        android:layout_alignParentRight="true"
        android:layout_alignTop="@id/text_dict_word"
        android:src="@drawable/add_danciben"
        android:background="@android:color/transparent"
        android:scaleType="fitXY"/>


    
    <RelativeLayout
        android:id="@+id/phonetic_bar" 
        android:layout_width="match_parent"
        android:layout_marginLeft="22dp"
        android:layout_height="40dp"
        android:layout_below="@id/text_dict_word">
        <ImageButton 
            android:id="@+id/image_btn_dict_horn_accent_eng"
            android:layout_height="match_parent"
            android:layout_marginTop="7dp"
            android:layout_marginBottom="7dp"
            android:layout_width="30dp"
            android:background="@android:color/transparent"
            android:src="@drawable/horn_dict"
            android:scaleType="fitCenter"
            />
        <TextView 
            android:id="@+id/text_dict_phosymbol_eng"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:text="英[fanted]"
            android:gravity="center_vertical"
            android:textColor="#6C6C6C"
            android:textSize="14sp"
            android:layout_toRightOf="@id/image_btn_dict_horn_accent_eng"/>
        <TextView 
            android:id="@+id/text_dict_phosymbol_divider"
            android:layout_height="match_parent"
            android:layout_width="50dp"
            android:text="/"
            android:gravity="center"
            android:textColor="#6C6C6C"
            android:textSize="14sp"
            android:layout_toRightOf="@id/text_dict_phosymbol_eng"/>
        
        <ImageButton 
            android:id="@+id/image_btn_dict_horn_accent_usa"
            android:layout_height="match_parent"
            android:layout_marginTop="7dp"
            android:layout_marginBottom="7dp"
            android:layout_width="30dp"
            android:background="@android:color/transparent"
            android:src="@drawable/horn_dict"
            android:scaleType="fitCenter"
            android:layout_toRightOf="@id/text_dict_phosymbol_divider"
            />
        
        <TextView 
            android:id="@+id/text_dict_phosymbol_usa"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:text="美[fan'ted]"
            android:gravity="center_vertical"
            android:textColor="#6C6C6C"
            android:textSize="14sp"
            android:layout_toRightOf="@id/image_btn_dict_horn_accent_usa"/>
        
        
    </RelativeLayout>

这是两个TextView ,释义的TextView使用了一个LayerList做背景,布局代码:

<LinearLayout 
        android:id="@+id/dict_interpret_divider"
        android:layout_height="20dp"
        android:layout_width="match_parent"
        android:layout_marginLeft="10dp"
        android:layout_below="@id/phonetic_bar"
        android:orientation="horizontal">
        <ImageView 
            android:layout_width="30dp"
            android:layout_height="match_parent"
            android:src="@drawable/right_cursor"/>
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="基本释义"
            android:textSize="14sp"
            android:textColor="#00A2DC"
            android:gravity="center_vertical"/>
        
    </LinearLayout>
    
      
    <TextView 
        android:id="@+id/text_dict_interpret"
        android:layout_below="@id/dict_interpret_divider"
        android:layout_width="match_parent"
        android:layout_margin="10dp"
        android:layout_height="80dp"
        android:background="@drawable/layer_list_dict_item_back"
        android:padding="12dp"
        android:text="不切实际的
srge了然于心fsfg"
        android:textSize="14sp"
        android:textColor="#3C3C3C"
        android:lineSpacingMultiplier="1.2"/>
layer_list_dict_item_back  layerList位于drawable文件夹中,可搜索layerlist的使用方法学习
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item >
        <shape >
            <corners android:radius="4dp"/>
            <solid android:color="#D0D0D0"/>
        </shape>
    </item>
    <item android:left="0.8dp" android:top="0dp" android:right="2dp" android:bottom="2dp">
        <shape >
            <corners android:radius="4dp"/>
            <solid android:color="#FEFEFE"/> 
        </shape>
    </item>

</layer-list>

 

这是一个ListView,它也采用了layerlist作背景。

<LinearLayout 
        android:id="@+id/dict_sentence_divider"
        android:layout_height="20dp"
        android:layout_width="match_parent"
        android:layout_marginLeft="10dp"
        android:layout_below="@id/text_dict_interpret"
        android:orientation="horizontal">
        <LinearLayout 
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="2"
            >
            <ImageView 
                android:layout_width="30dp"
                android:layout_height="match_parent"
                android:src="@drawable/right_cursor"/>
            <TextView 
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:text="例句"
                android:textSize="14sp"
                android:textColor="#00A2DC"
                android:gravity="center_vertical"/>
            
        </LinearLayout>
        
        <RelativeLayout 
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:layout_weight="1">
            
            <ImageView
                android:id="@+id/dict_jinshan_ico" 
                android:layout_height="match_parent"
                android:layout_width="30dp"
                android:layout_alignParentRight="true"
                android:layout_marginRight="15dp"
                android:src="@drawable/jinshan_ico"/>
            <TextView 
                android:layout_height="match_parent"
                android:layout_width="wrap_content"
                android:gravity="bottom"
                android:layout_toLeftOf="@id/dict_jinshan_ico"
                android:text="supported by iCIBA"
                android:textColor="#6C6C6C"
                android:textSize="10sp"/>
            
        </RelativeLayout>
        
        
    </LinearLayout>
    
   
    <ListView 
        android:id="@+id/listview_dict_sentence"
        android:layout_below="@id/dict_sentence_divider"
        android:layout_width="match_parent"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:padding="12dp"
         android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@drawable/layer_list_dict_item_back"
        android:divider="#8C8C8C"
        android:dividerHeight="0px"
        >
        
    </ListView>

 

设计好布局文件后,我们很容易理解各个控件的作用,接下来我们就要写Activity子类,用于实例化各个控件,设置监听器,实现各个按钮的功能。

在写Activity之前,首先就成员变量的命名做一个说明,因为个Activity中的控件很多,如果随便命名很容易混乱,这里我采用了一种根据属性和类命名的方法,大家可以参考:

比如 上面有一个“放大镜”的搜索按钮,这是一个ImageButton 同时它是属于DictActivity的,它的功能是开始查单词,那么就将这个ImageButton对象命名为:

           ImageButton  imageBtnDictSearch=(ImageButton)findViewById(R.id.image_btn_dict_search);

在设置布局文件后把id也设置成相同的名字,这样就不会搞混了,根据我的经验这种命名方式非常高效。

下面就给出DictActivity类:

package com.carlos.yueci;

import java.security.KeyStore;

import java.util.ArrayList;
import java.util.Currency;
import java.util.HashMap;

import com.carlos.adapter.DictSentenceListAdapter;
import com.carlos.database.DataBaseHelper;
import com.carlos.music.Mp3Player;
import com.carlos.yueci.R;
import com.carlos.wordcontainer.Dict;
import com.carlos.wordcontainer.WordValue;


import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.inputmethodservice.Keyboard.Key;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.method.ScrollingMovementMethod;
import android.view.KeyCharacterMap.KeyData;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.TextView.OnEditorActionListener;

public class DictActivity extends Activity{
    
    public TextView textDictWord=null;
    public TextView textDictPhonSymbolEng=null;
    public TextView textDictPhonSymbolUSA=null;
    public TextView textDictInterpret=null;
    public ListView listViewDictSentence=null;
    public ImageButton imageBtnDictAddToWordList=null;
    public ImageButton imageBtnDictHornEng=null;
    public ImageButton imageBtnDictHornUSA=null;
    public ImageButton imageBtnDictSerach=null;
    public ImageButton imageBtnDictBackToGeneral=null;
    public ImageButton imageBtnDictDelteEditText=null;
    
    public Button buttonDictDialogConfirm=null;
    public Button buttonDictDialogCancel=null;
    
    public EditText editTextDictSearch=null;
    
    public Dict dict=null;
    
    public WordValue w=null;
    
    public DataBaseHelper dbGlossaryHelper=null;
    public SQLiteDatabase dbGlossaryR=null;
    public SQLiteDatabase dbGlossaryW=null;
    
    
    public Mp3Player mp3Box=null;
    
    public static String searchedWord=null;
    
    public Handler dictHandler=null;
    
    public void initial(){
        textDictWord=(TextView) findViewById(R.id.text_dict_word);
        textDictInterpret=(TextView)findViewById(R.id.text_dict_interpret);
        textDictPhonSymbolEng=(TextView)findViewById(R.id.text_dict_phosymbol_eng);
        textDictPhonSymbolUSA=(TextView)findViewById(R.id.text_dict_phosymbol_usa);
        listViewDictSentence=(ListView)findViewById(R.id.listview_dict_sentence);
        
        imageBtnDictAddToWordList=(ImageButton)findViewById(R.id.image_btn_dict_add_to_wordlist);
        imageBtnDictBackToGeneral=(ImageButton)findViewById(R.id.image_btn_dict_back_to_general);
        imageBtnDictHornEng=(ImageButton)findViewById(R.id.image_btn_dict_horn_accent_eng);
        imageBtnDictHornUSA=(ImageButton)findViewById(R.id.image_btn_dict_horn_accent_usa);
        imageBtnDictSerach=(ImageButton)findViewById(R.id.image_btn_dict_search);
        imageBtnDictDelteEditText=(ImageButton)findViewById(R.id.image_btn_dict_delete_all);
        
        
        editTextDictSearch=(EditText)findViewById(R.id.edit_text_dict);
        editTextDictSearch.setOnEditorActionListener(new EditTextDictEditActionLis());
        dict=new Dict(DictActivity.this, "dict");
        mp3Box=new Mp3Player(DictActivity.this, "dict");
        dbGlossaryHelper=new DataBaseHelper(DictActivity.this, "glossary");
        dbGlossaryR=dbGlossaryHelper.getReadableDatabase();
        dbGlossaryW=dbGlossaryHelper.getWritableDatabase();
    
        
        dictHandler=new Handler(Looper.getMainLooper());
        
        //对searchedWord进行初始化
        Intent intent=this.getIntent();
        searchedWord=intent.getStringExtra("word");
        if(searchedWord==null)
            searchedWord="";
        //设置查找的文本
        textDictWord.setText(searchedWord);

    }
    
    
    /**
     * 该方法可能需要访问网络,因此放在线程里进行
     * @param word
     */
    public void searchWord(String word){
        //调用该方法后首先初始化界面
        dictHandler.post(new RunnableDictSetTextInterface(searchedWord, "", "", "", null, null));
        w=null;    //对w进行初始化
        if(dict.isWordExist(word)==false){  //数据库中没有单词记录,从网络上进行同步                
            if((w=dict.getWordFromInternet(word))==null ||w.getWord().equals("")){
                return;
            }
                //错词不添加进词典
            dict.insertWordToDict(w, true);   //默认添加到词典中
        }//能走到这一步说明从网上同步成功,数据库中一定存在单词记录
        w=dict.getWordFromDict(word);
        if(w==null){             //这里又进一步做了保护,若词典中还是没有,那么用空字符串代替
            w=new WordValue();
        }
        String searchStr=w.getWord();
        String phoSymEng=w.getPsE();  
        String phoSymUSA=w.getPsA();
        String interpret=w.getInterpret();
        ArrayList<String> sentList=w.getOrigList();  //一定不会是null
        ArrayList<String> sentInChineseList=w.getTransList();
        dictHandler.post(new RunnableDictSetTextInterface(searchedWord, phoSymEng, phoSymUSA, interpret, sentList, sentInChineseList));
        if(phoSymEng.equals("")==false && phoSymUSA.equals("")==false){    //只有有音标时才去下载音乐
            
            mp3Box.playMusicByWord(searchedWord, Mp3Player.ENGLISH_ACCENT, true, false);
            mp3Box.playMusicByWord(searchedWord, Mp3Player.USA_ACCENT, true, false);
            
        }
    }
    

    
    public void setOnClickLis(){
        imageBtnDictBackToGeneral.setOnClickListener(new IBDictBackToGeneralClickLis() );
        imageBtnDictHornEng.setOnClickListener(new IBDictPlayMusicByAccentClickLis(Mp3Player.ENGLISH_ACCENT));
        imageBtnDictHornUSA.setOnClickListener(new IBDictPlayMusicByAccentClickLis(Mp3Player.USA_ACCENT));
        imageBtnDictAddToWordList.setOnClickListener(new IBDictAddWordToGlossaryClickLis());
        imageBtnDictDelteEditText.setOnClickListener(new IBDictDeleteEditTextClickLis());
        imageBtnDictSerach.setOnClickListener(new IBDictSearchClickLis());
    }
    
    
    public void showAddDialog(){
        if(searchedWord==null)
            return;
        AlertDialog dialog=new AlertDialog.Builder(DictActivity.this).create();
        dialog.show();
        Window window=dialog.getWindow();
        window.setContentView(R.layout.dialog_if_layout);
        buttonDictDialogConfirm=(Button)window.findViewById(R.id.dialog_confirm);
        buttonDictDialogCancel=(Button)window.findViewById(R.id.dialog_cancel);
        buttonDictDialogConfirm.setOnClickListener(new BDictDialogConfirmClickLis(dialog));
        buttonDictDialogCancel.setOnClickListener(new BDictDialogCancelClickLis(dialog));
        TextView dialogText=(TextView)window.findViewById(R.id.dialog_text);
        dialogText.setText("把"+searchedWord+"添加到单词本?");
        
    }
    
    public void insertWordToGlossary(){
        if(w==null || w.getInterpret().equals("")){
            Toast.makeText(DictActivity.this, "单词格式错误", Toast.LENGTH_SHORT).show();
            return;                   //若是不是有效单词,那么将不能添加到单词本
        }
        boolean isSuccess=dbGlossaryHelper.insertWordInfoToDataBase(searchedWord, w.getInterpret(), false);
        if(isSuccess){
            Toast.makeText(DictActivity.this, "添加成功", Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(DictActivity.this, "单词已存在", Toast.LENGTH_SHORT).show();
        }
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dict);
        
        

    
        initial();
        setOnClickLis();
        
        
        new ThreadDictSearchWordAndSetInterface().start();
        
        
          
    }

    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
        mp3Box.isMusicPermitted=true;
    }
    
    
    
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        mp3Box.isMusicPermitted=false;
        super.onPause();
    }



    public class ThreadDictSearchWordAndSetInterface extends Thread{

        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
            searchWord(searchedWord);
        }
        
    }
    
    public class RunnableDictSetTextInterface implements Runnable{
        String searchStr=null;
        String phoSymEng=null;
        String phoSymUSA=null;
        String interpret=null;
        ArrayList<String> sentList=null;
        ArrayList<String> sentInChineseList=null;
        

        public RunnableDictSetTextInterface(String searchStr, String phoSymEng,
                String phoSymUSA, String interpret, ArrayList<String> sentList,
                ArrayList<String> sentInChineseList) {
            super();
            this.searchStr = searchStr;
            this.phoSymEng = "英["+phoSymEng+"]";
            this.phoSymUSA = "美["+phoSymUSA+"]";
            this.interpret = interpret;
            this.sentList = sentList;
            this.sentInChineseList = sentInChineseList;
        }


        @Override
        public void run() {
            // TODO Auto-generated method stub
            textDictWord.setText(searchStr);
            textDictPhonSymbolEng.setText(phoSymEng);
            textDictPhonSymbolUSA.setText(phoSymUSA);
            textDictInterpret.setText(interpret);
            if(sentList==null ||sentInChineseList==null){     //对链表为空进行防护
            //    textDictSentence.setText("");
                return;
            }
            int count=0;
            if(sentList.size()<=sentInChineseList.size()){
                count=sentList.size();
            }else{
                count=sentInChineseList.size();             //保护机制,这里取两者长度最小值,但一般二者长度相等
            }
            ArrayList<HashMap<String,Object>> list=new ArrayList<HashMap<String,Object>>();
            for(int i=0; i<count;i++){
    //            sb.append(sentList.get(i)+"
"+sentInChineseList.get(i)+"

");
                HashMap<String,Object> map=new HashMap<String, Object>();
                map.put("sentence", sentList.get(i)+"
"+sentInChineseList.get(i));
                list.add(map);
            }
    //        textDictSentence.setText(sb.toString());
            DictSentenceListAdapter adapter=new DictSentenceListAdapter(DictActivity.this, R.layout.dict_sentence_list_item, list, new String[]{"sentence"}, new int[]{R.id.text_dict_sentence_list_item});
            listViewDictSentence.setAdapter(adapter);
            
        }
        
    }
    
    class IBDictBackToGeneralClickLis implements OnClickListener{

        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            DictActivity.this.finish();
            
        }
        
    }
    
    class IBDictPlayMusicByAccentClickLis implements OnClickListener{

        public int accentTemp=0;
        
        public IBDictPlayMusicByAccentClickLis(int accentTemp) {
            super();
            this.accentTemp = accentTemp;
        }

        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            
            mp3Box.playMusicByWord(searchedWord, accentTemp, false, true);
            
        }
        
    }
    
    class IBDictAddWordToGlossaryClickLis implements OnClickListener{

        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            showAddDialog();
        }
        
    }
    
    class IBDictDeleteEditTextClickLis implements OnClickListener{

        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            editTextDictSearch.setText("");
        }
        
    }
    
    class BDictDialogConfirmClickLis implements OnClickListener{

        AlertDialog dialog=null;
        public BDictDialogConfirmClickLis(AlertDialog dialog){
            this.dialog=dialog;
        }
        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            insertWordToGlossary();
            dialog.cancel();
        }
        
    }
    
    class BDictDialogCancelClickLis implements OnClickListener{
        AlertDialog dialog=null;
        public BDictDialogCancelClickLis(AlertDialog dialog){
            this.dialog=dialog;
        }
        
        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            dialog.cancel();
        }
        
    }
    
    class EditTextDictEditActionLis implements OnEditorActionListener{

        @Override
        public boolean onEditorAction(TextView arg0, int arg1, KeyEvent arg2) {
            // TODO Auto-generated method stub
            if(arg1==EditorInfo.IME_ACTION_SEARCH || arg2!=null&&arg2.getKeyCode()==KeyEvent.KEYCODE_ENTER){
                startSearch();
                return true;
            }
            
            return false;
        }
        
    }
    
    
    class IBDictSearchClickLis implements OnClickListener{

        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            startSearch();
            
        }
        
    }
    
    public void startSearch(){
        
        String str=editTextDictSearch.getText().toString();
        if(str==null || str.equals(""))
            return;
        searchedWord=str;
        new ThreadDictSearchWordAndSetInterface().start();
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(editTextDictSearch.getWindowToken(), 0);
        
    }

}

我把所有的findViewById全部放在了initial()方法中,方便调用;这个Activity类的主要目的就是给各个按钮设置监听器,这里对监听器类的命名我也做了一个统一的规定:

还是以“搜索”按钮为例:搜索按钮是一个ImageButton,是属于DictActivity类,是实现搜索功能,需要设置一个ClickListener,那么我们创建的一个OnClickListener实现类的名字就叫:             class       IBDictSearchClickLis   implements OnCLickListner{  };

 

这里还涉及到使用AlertDialog  ,关于使用方法可以百度之,比较简单,其余部分都是利用我前面介绍的5个后台类进行对单词的操作,各个函数的功能都有注释。

另外要注意在子线程中是不能操作UI的,这里需要DictActivity实例化一个Handler对象,通过Runnable向UI发送信息,不推荐用Message

这里单词的例句使用到了ListView,关于ListView 可以参考我去年写的两篇关于ListView的教程:

http://www.cnblogs.com/carlos-vic/p/Carlos_V_Android_5.html

http://www.cnblogs.com/carlos-vic/p/Carlos_V_Android_6.html

这里进把基本ListView所需要的ListItem的布局文件和适配器BaseAdapter贴上来,最最基本的一个ListView:

listItem布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
     android:paddingTop="8dp"
     android:paddingBottom="8dp"
     android:paddingLeft="3dp"
     android:paddingRight="3dp"
     android:background="@drawable/list_item_sentence_back" >
    
    <TextView 
        android:id="@+id/text_dict_sentence_list_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:textColor="#3C3C3C"
        android:textSize="14sp"/>
    

</LinearLayout>

适配器类:

package com.carlos.adapter;

import java.util.ArrayList;
import java.util.HashMap;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class DictSentenceListAdapter extends BaseAdapter{
    
    private Context context=null;
    private int resources;
    private ArrayList<HashMap<String,Object>> list=null;
    private String[] from;
    private int[] to;
    
    
    /**
     * 这里仿照的是SimpleAdapter的形参列表
     * @param context
     * @param Resources
     * @param list
     * @param from
     * @param to
     */
    
    public DictSentenceListAdapter(Context context, int resources,
            ArrayList<HashMap<String, Object>> list, String[] from, int[] to) {
        super();
        this.context = context;
        this.resources = resources;
        this.list = list;
        this.from = from;
        this.to = to;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return list.size();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return arg0;
    }

    @Override
    public View getView(int position, View contentView, ViewGroup arg2) {
        // TODO Auto-generated method stub
        LayoutInflater inflater=LayoutInflater.from(context);
        contentView=inflater.inflate(resources, null);
        TextView text=(TextView)contentView.findViewById(to[0]);
        text.setText((String)(list.get(position).get(from[0])));
        return contentView;
    }

}

 

  这样,“悦词-i背单词”应用的查单词功能就完全实现了,另外这里的布局文件中用到了很多背景资源,

等所有UI搭建完成后我会把资源文件上传上来,今天的教程就到这里了~

 

 

 

 

 

 



 


初中背单词

怎样才能把这么多单词背下来呢?最重要的一点,就是:如果想比别人成功,就一定要走捷径。不要期盼自己比别人幸运,也不要指望自己比别人更聪明或者更勤奋。从智力上说,从机遇上说,自己和别人都是差不了多少的,想超过和自己差不多的人,就一定要走捷径,捷径,捷径!
背单词捷径的第一条,就是:一定要每次都大量地背。
因为自己不比别人聪明,所以背完单词,别人忘掉五分之一,自己决不会比别人忘得少。然而,别人每天背十个单词,自己却可以背一百个,忘掉五分之一,还剩八十个,是别人最聪明状态下的十倍。每天一百个是最低限。其实背到后来您会发现这个要求并不高,一个月后,您可能自然而然地就背到三百或者五百。
这一百个要分成四组来背,上午三十,中午十个,下午三十,晚上三十。第二天早晨复习以前没背下来的词。背的时候,要一目十词(注意,是十个而不是更多或更少),不要认认真真背,因为没有认认真真的时间。一边看一边读每个词的读音,默读也成。看完后回忆一遍,回忆不起来的再看。这次背的目的在于留下个大概印象,下次看见能知道这个词,所以背到大部分都能回忆得起来就成了,把剩下的词单独抄出来。
背单词捷径的第二条,就是:背字典!为什么要背字典呢?因为字典上每个词的解释比较全面,而且相同字母开头的单词都集中在一起。不是什么字典都可以拿来背的,一定要找只包含自己想背的词的字典。另外,最好有解释和例句。而且,一定要有音标!一般教材课文后面的词汇表都是为那些认认真真听课的好学生准备的,想走捷径就千万不要去背那些东西。
背字典的时候,按开头字母(Z,Y,X,Q,J,K,U)(V,W,N,O,L)(FG,IT,HM,BDE,R)(C,P,S,A)的顺序背,其中C,P,S,A每个都要分三部分背。这样背有几个好处:(一)能增加成就感,提高兴趣。至于为什么,您翻翻字典就明白了。(二)便于清楚地知道那些单词已经背过,那些还没背。(三)能先把最基本的词先掌握。
三万单词里,分为三个等级:三千到四千,八千到一万,两万二到三万。也就是说,您得分别准备三本字典。这几个等级之间各自有非常不同的特性,所以需要分别用不同方法背。俺当时没有认识到这一点,所以在从一万到三万之间走了一段弯路,浪费了一些时间,不然或许能突破到五万吧。
所以,背单词捷径的下面这条就有了三个分支:
背单词捷径的第三条,就是:和单词多见面。一个单词能不能记住,取决于和它在不同场合见面的频率,不在于每次看着它的时间长短(同样规律也适合于泡MM)。一般想记住一个单词,每星期要和它在“不同场合”见三到四次面。俺在上文中提到大量背的时候,不要抠某一个字记住与否就是这个意思。因为是否一见钟情都是无所谓的,关键在于有更多不同类型的见面机会。不过,根据要背的单词的等级不同,增加见面机会的方式也有所不同。
第一个分支:瞎听!三千到四千这个等级,是非常常用的单词,而且几乎囊括了表达最基本思想所需要的一切词汇。每篇文章中百分之八十都是这些词汇,而且这些词都是最基本的语素(或称“词根”),就是分割到最小无法再分割,互相之间也没什么类似之处的东西。对付这些词的最好方法,就是进行大量的,不间断的,简单的初级听力练习。因为阅读材料中,还有百分之二十其他词汇,所以光凭这个等级的词还看不懂那些阅读材料。但是听力练习都是最基本的对话,而且发音一般很标准,多听能够增加单词的重复率,而且可以为以后背八千到一万那个等级的词打下语音基础。
听的时候,要分精听和泛听两部分。精听当然是指每个词都要弄懂,俺着重讲一下泛听。泛听是最重要的,因为掌握语速和......余下全文>>
 
背单词的技巧

词汇复习方法

词汇对于英语学习的重要性,在这里不再赘述了。总之一句话,要想学好英语,要想顺利通过各种英语考试,积累一定量的词汇都是必须的,这点无用质疑。
对于6级词汇,由于其大大区别于4级词汇难度,而向中级难度的词汇过度,是需要下一番工夫专门记忆的。通过对十几套词汇真题的统计,我们可以得到这样的提示:对动词要给予最高程度的重视,基本要求是在阅读文章中见到的都应该认识。形容词,副词(以形容词为主)的表现力也很丰富,因而也是学习的重点。名词基本上都是比较常见的,不会出现极专业化的词汇,词组考得就更少了,建议大家在阅读中记忆常见的,而不需专门记忆。
关于记忆方法,其实是比较仁者见仁的东西,我在这里要说的只是背单词的几个基本原则。6级词汇有1500左右,我建议大家把这1500个分为30个list(每个list50词左右),至于先背A后背A等问题,我觉得无所谓,不少朋友说由A背到Z太心烦,可偶从4—6—托—G就是按照这样的次序背的,感觉也不坏呀!这完全是个人习惯吧。
具体操作:
1。第一遍要快,每天一个list,50个词,一个月完成。
有人做过一个统计,普通人每日记忆词汇的极限是80个(全部新词),每天背50个,而且还有认识的,应该不算很多吧?:)第一遍是最难背的,一定要坚持下来!这一遍的目的是全面掌握大纲词汇。最新的一次6级考试证明,只背词频已经远远不够,还是掌握的全面些为好。背完第一遍就要马上转到阅读,听力等的复习中来,进一步巩固词汇。到这时,每天也要抽出一定的时间(半小时以下)专门复习词汇,这个时间应该越来越短,当你不到半小时就能复习一遍所有词汇时,词汇就基本背完了。

附:偶的背词方法:
第1天 list 1
第2天 list 2 list 1
第3天 list 3 list 2 list 1
第4天 list 4 list 3 list 2 list 1
第5天 list 5 list 4 list 3 list 2 list 1
第五天过后,list1已经背完5遍
第6天 list 6 list 5 list 4 list 3 list 2
第7天 list 7 list 6 list 5 list 4 list 3

```````
这样继续下去,直到所有的list前都被你划了一个“正”:)

2。被单词要少量多次。
我推荐每天早晚各抽出45分钟背,平时一有空闲,就可以复习。

3。学而时习之。
在不熟悉的词前加标号,以便第2天重点复习。
4。结合做题背单词
推荐丁老师的《通过练习学词汇》,作为阶段成果的检验。即便作得很差也可以激励你更加努力。
5。特殊词要用特殊记法。
比如abacus(爱拨个死),就是算盘;dilute=di(分开)+lute(冲) 就是“冲淡”的意思
6。持之以恒.

特别提示:如果第6点做不到,以上所有都没有用!!

洋洋洒洒,废话不少。希望对大家能有些用。祝大家早日拿下词汇,顺利通过那个令你又爱又恨的英语6级考试!!

以下是本人在背英语四级单词的时候,总结出来的三个小窍门,经过亲身体验觉得非常不错现向大家推荐,各位网友朋友们不妨自己试一试:

1.背单词要背得好,要背得快,最基本的原则是脑子不断地想单词,让单词不断地从脑子里过,看书看10遍,还不如脑子过一遍。要做到单词在脑子里过的次数比在书本上过的次数多得多,要做到完全抛开书本,不依赖书本,不拿书的时候也在想单词、背单词。要尽量在单词被忘记之前在脑子里过一遍,这样,它留给你的印象要深得多,就算以后忘记......余下全文>>
 

http://www.bkjia.com/Androidjc/870595.htmlwww.bkjia.comtruehttp://www.bkjia.com/Androidjc/870595.htmlTechArticle和我一起开发Android应用(三)——“悦词-i背单词”词典功能实现,android-i 接上一讲。本节我们把词典功能基本实现,首先上一个效果图,...

本文源自: 环亚娱乐