2015年的Android案例之旅
案例七:电子词典
知识点:
1.自动完成文本框(AutoCompleteTextView)
AutoCompleteTextView是从EditText派生出来的,当用户输入一定字符之后,AutoCompleteTextView会显示一个下拉菜单,供用户选择,当用户选择某个菜单之后,内容会被填充到该文本中。
使用AutoCompleteTextView需要设置一个Adapter,该Adapter封装了预设的提示文本
2.SQLiteDataBase数据库
3.Adapter适配器
涉及文件:
res->layout->activity_main.xml 布局文件
res->layout->word_list_item.xml 布局文件
res->raw-> dictionary.db 词典数据库
res->values->strings 资源文件之字符串资源
res->values->color 资源文件之颜色资源
res->AndroidManifest.xml 系统清单文件主要添加SD卡相关权限
src->package->MainActivity.java java文件
activity_main.xml
<!-- 线性布局 --><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#ff808080"> <!-- 相对布局 用于设置搜索框和搜索按钮 --> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- 定义自动完成文本框,供用户输入单词 --> <AutoCompleteTextView android:id="@+id/word" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:ems="20" android:layout_toLeftOf="@+id/searchWord"/> <!-- 搜索按钮,供用户点击查询单词 --> <Button android:id="@+id/searchWord" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:text="@string/search"/> </RelativeLayout> <!-- 查询结果 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/result"/> <!-- 用户显示查询的结果 --> <TextView android:id="@+id/show" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:textColor="@color/blue"/></LinearLayout>
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:gravity="center_vertical" android:minHeight="?android:attr/listPreferredItemHeight" android:paddingLeft="6dip" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/gray" />
MainActivity.java
package com.example.mydicitonary;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import android.app.Activity;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.os.Bundle;import android.support.v4.widget.CursorAdapter;import android.text.Editable;import android.text.TextWatcher;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.AutoCompleteTextView;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity { //定义Log标签 private static final String TAG = "DICITONARY"; //声明控件对象 private Button search; private TextView show; private AutoCompleteTextView actv; //用到SQLiteDateBase //定义数据库的存放路径 private static final String DATEBASE_PATH = android.os.Environment .getExternalStorageDirectory().getAbsolutePath() + "/dictionary"; //定义数据库的名字 private static final String DATEBASE_NAME = "dictionary.db"; private SQLiteDatabase database; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i(TAG, "DICITONARY is onCreate"); //获取布局中的控件 init(); //打开数据库 database = openDateBase(); //监听事件处理 listener(); } /** * @oaram 初始化控件 */ private void init(){ search = (Button)this.findViewById(R.id.searchWord); show = (TextView)this.findViewById(R.id.show); actv = (AutoCompleteTextView)this.findViewById(R.id.word); } /** * @param 处理监听事件 */ private void listener(){ //按钮点击事件 search.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { String result = "未查到该单词信息"; //查询指定的单词 String sql = "select chinese from t_words where english=?"; Cursor cursor = database.rawQuery(sql, new String[]{ actv.getText().toString() }); if(cursor.getCount()>0){ // 必须使用moveToFirst方法将记录指针移动到第1条记录的位置 cursor.moveToFirst(); result = cursor.getString(cursor.getColumnIndex("chinese")).replace("&", "&"); } //将结果显示到TextView中 show.setText(actv.getText().toString() +"\n"+result); } }); //文本变动事件 actv.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub } @Override public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable s) { Cursor cursor = database.rawQuery( "select english as _id from t_words where english like ?", new String[] { s.toString() + "%" }); //新建新的Adapter DictionaryAdapter dictionaryAdapter = new DictionaryAdapter(MainActivity.this, cursor, true); //绑定适配器 actv.setAdapter(dictionaryAdapter); } }); } //自定义Adapter类 public class DictionaryAdapter extends CursorAdapter{ //对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入; //对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获得其中的界面元素。 private LayoutInflater layoutInflater; public DictionaryAdapter(Context context, Cursor c, boolean autoRequery) { super(context, c, autoRequery); layoutInflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public CharSequence convertToString(Cursor cursor) { return cursor == null ? "" : cursor.getString(cursor .getColumnIndex("_id")); } //将单词信息显示到列表中 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 arg2) { View view = layoutInflater.inflate(R.layout.word_list_item, null); setView(view, cursor); return view; } } /** * @param 返回一个SQLiteDatabase对象 * @return */ private SQLiteDatabase openDateBase(){ try { // 获得dictionary.db文件的绝对路径 String databaseFileName = DATEBASE_PATH + "/" + DATEBASE_NAME; File dir = new File(DATEBASE_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[9128]; int count = 0; // 开始复制dictionary.db文件 while((count = is.read(buffer))!=-1){ fos.write(buffer, 0, count); } //关闭文件流 is.close(); fos.close(); } // 打开/sdcard/dictionary目录中的dictionary.db文件 SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase( databaseFileName, null); return database; } catch (Exception e) { // TODO: handle exception } return null; }}
<?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:gravity="center_vertical" android:minHeight="?android:attr/listPreferredItemHeight" android:paddingLeft="6dip" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/gray" />