实现的功能:
<1> 使用AutoCompleteTextView和MultiAutoCompleteTextView实现对绑定字符数组的提示;
<2> 使用AutoCompleteTextView和MultiAutoCompleteTextView实现对从手机联系人读取的姓名进行提示;
<3> 实现在文本框输入字符后,将输入的字符存入数据库中,下次再输入字符时,将从数据库中读取保存的字符串进行提示,保存的字符串不能重复,在数据库中每次插入时进行判断,如果已存在于数据库中,则更新保存的时间,如果不存在,则重新插入,且可以设置数据库中最多能够保存多少条数据,当达到该最大值时,没插入一条数据,同事删除数据库保存时间最久的那一条数据。
完整代码如下:
strings.xml
------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, MainActivity!</string>
<string name="app_name">文本自动提示</string>
<string name="single">输入内容自动完成文本框</string>
<string name="multi">多次输入内容自动完成文本框</string>
<string name="normal_single">自定义数组提示:</string>
<string name="normal_multi">自定义数组提示:</string>
<string name="contacts_single">提示联系人:</string>
<string name="contacts_multi">提示联系人:</string>
<string name="self_signle">自动提示输入的字符</string>
<string name="self_text">提示已输入的字符:</string>
<string name="save">保存</string>
</resources>
------------------------------------------------------------------------------
main.xml
------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/single" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/normal_single" />
<AutoCompleteTextView
android:id="@+id/single1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/contacts_multi" />
<AutoCompleteTextView
android:id="@+id/single2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1" />
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/multi" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/normal_multi" />
<MultiAutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
android:id="@+id/multi1" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/contacts_multi" />
<MultiAutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
android:id="@+id/multi2" />
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/self_signle" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/self_text" />
<AutoCompleteTextView
android:id="@+id/single3"
android:layout_width="150dip"
android:layout_height="wrap_content"
android:completionThreshold="1" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
</LinearLayout>
</LinearLayout>
------------------------------------------------------------------------------
AndroidManifest.xml
------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.am321.ddc.autocomplete"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<uses-library android:name="android.test.runner" />
<activity android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider android:name=".db.DBProvider" android:authorities="cn.am321.ddc.autocomplete"/>
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="cn.am321.ddc.autocomplete" />
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
</manifest>
------------------------------------------------------------------------------
MainActivity.java
------------------------------------------------------------------------------
public class MainActivity extends Activity {
private AutoCompleteTextView autoCompleteTextView1;
private AutoCompleteTextView autoCompleteTextView2;
private AutoCompleteTextView autoCompleteTextView3;
private MultiAutoCompleteTextView multiAutoCompleteTextView1;
private MultiAutoCompleteTextView multiAutoCompleteTextView2;
private Button button;
private ArrayAdapter<String> adapter3;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
autoCompleteTextView1 = (AutoCompleteTextView) this.findViewById(R.id.single1);
autoCompleteTextView2 = (AutoCompleteTextView) this.findViewById(R.id.single2);
autoCompleteTextView3 = (AutoCompleteTextView) this.findViewById(R.id.single3);
multiAutoCompleteTextView1 = (MultiAutoCompleteTextView) this.findViewById(R.id.multi1);
multiAutoCompleteTextView2 = (MultiAutoCompleteTextView) this.findViewById(R.id.multi2);
button = (Button) this.findViewById(R.id.button);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, COUNTRIES);
autoCompleteTextView1.setAdapter(adapter);
multiAutoCompleteTextView1.setAdapter(adapter);
multiAutoCompleteTextView1.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
ContentResolver content = getContentResolver();
Cursor cursor = content.query(Contacts.People.CONTENT_URI,//
PEOPLE_PROJECTION, null, null, Contacts.People.DEFAULT_SORT_ORDER);
ContactListAdapter adapter2 = new ContactListAdapter(this, cursor);
// adapter2.notifyDataSetChanged();
autoCompleteTextView2.setAdapter(adapter2);
multiAutoCompleteTextView2.setAdapter(adapter2);
multiAutoCompleteTextView2.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
adapter3 = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, DBOperation.getAllMessages(this));
autoCompleteTextView3.setAdapter(adapter3);
// multiAutoCompleteTextView2.setAdapter(adapter2);
// multiAutoCompleteTextView2.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
final String message = autoCompleteTextView3.getText().toString();
if (!"".equals(message) && message != null) {
new Thread(new Runnable() {
public void run() {
DBOperation.addMessage(MainActivity.this, message);
Message msg = new Message();
myHandler.sendMessage(msg);
}
}).start();
}
}
});
}
Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
adapter3 = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_dropdown_item_1line, DBOperation.getAllMessages(MainActivity.this));
autoCompleteTextView3.setAdapter(adapter3);
super.handleMessage(msg);
}
};
public static class ContactListAdapter extends CursorAdapter {
private ContentResolver mContentResolver;
public ContactListAdapter(Context context, Cursor c) {
super(context, c);
mContentResolver = context.getContentResolver();
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final LayoutInflater inflater = LayoutInflater.from(context);
final TextView view = (TextView) inflater.inflate(android.R.layout.simple_dropdown_item_1line, parent, false);
view.setText(cursor.getString(5));
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
((TextView) view).setText(cursor.getString(5));
}
@Override
public CharSequence convertToString(Cursor cursor) {
return cursor.getString(5);
}
@Override
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
if (getFilterQueryProvider() != null) {
return getFilterQueryProvider().runQuery(constraint);
}
StringBuilder buffer = null;
String[] args = null;
if (constraint != null) {
buffer = new StringBuilder();
buffer.append("UPPER(");
buffer.append(Contacts.ContactMethods.NAME);
buffer.append(") GLOB ?");
args = new String[] { constraint.toString().toUpperCase() + "*" };
}
return mContentResolver.query(Contacts.People.CONTENT_URI, PEOPLE_PROJECTION,//
buffer == null ? null : buffer.toString(), args, Contacts.People.DEFAULT_SORT_ORDER);
}
}
private static final String[] PEOPLE_PROJECTION = new String[] { Contacts.People._ID, Contacts.People.PRIMARY_PHONE_ID, Contacts.People.TYPE, Contacts.People.NUMBER,
Contacts.People.LABEL, Contacts.People.NAME, };
static final String[] COUNTRIES = new String[] { "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra };
}
------------------------------------------------------------------------------
DBContext.java
------------------------------------------------------------------------------
public final class DBContext {
public static final String AUTHORITY = "cn.am321.ddc.autocomplete";
public static final class Messages implements BaseColumns{
public static final String TABLE_NAME = "messages";
public static final Uri CONTENT_URI = Uri.parse("content://"+ AUTHORITY +"/messages");
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd."+AUTHORITY+"."+TABLE_NAME;
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd."+AUTHORITY+"."+TABLE_NAME+"item";
public static final String MESSAGE_TIMESTAMP = "message_timestamp";
public static final String MESSAGE_STRING = "message_string";
}
}
------------------------------------------------------------------------------
DBProvider.java
------------------------------------------------------------------------------
public class DBProvider extends ContentProvider {
private static final String DATABASE_NAME = "ddc.db";
private static final int DATABASE_VERSION = 1;
private static final int MESSAGES = 1;
private static final int MESSAGES_ID = 2;
private DatabaseHelper mDBHelper;
private static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(DBContext.AUTHORITY, Messages.TABLE_NAME, MESSAGES);
uriMatcher.addURI(DBContext.AUTHORITY, Messages.TABLE_NAME + "/#", MESSAGES_ID);
}
private static class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper mInstance = null;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public static DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context);
}
return mInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + DBContext.Messages.TABLE_NAME //
+ "("//
//+ DBContext.Messages._ID + " INTEGER PRIMARY KEY,"//
+ DBContext.Messages.MESSAGE_TIMESTAMP + " TEXT,"//
+ DBContext.Messages.MESSAGE_STRING + " TEXT"//
+ ");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + DBContext.Messages.TABLE_NAME + ";");
onCreate(db);
}
}
@Override
public boolean onCreate() {
mDBHelper = DatabaseHelper.getInstance(this.getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
switch (uriMatcher.match(uri)) {
case MESSAGES:
qb.setTables(Messages.TABLE_NAME);
break;
case MESSAGES_ID:
qb.setTables(Messages.TABLE_NAME);
qb.appendWhere(Messages._ID + "=" + uri.getLastPathSegment());
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
SQLiteDatabase db = mDBHelper.getReadableDatabase();
Cursor cursor = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(this.getContext().getContentResolver(), uri);
return cursor;
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case MESSAGES:
return Messages.CONTENT_TYPE;
case MESSAGES_ID:
return Messages.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
String table_name = "";
String columnHack = "";
Uri CONTENT_URI;
switch (uriMatcher.match(uri)) {
case MESSAGES:
case MESSAGES_ID:
table_name = Messages.TABLE_NAME;
columnHack = Messages.TABLE_NAME;
CONTENT_URI = Messages.CONTENT_URI;
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
SQLiteDatabase qb = mDBHelper.getWritableDatabase();
long rowId = qb.insert(table_name, columnHack, values);
if (rowId > 0) {
Uri noteUri = ContentUris.withAppendedId(CONTENT_URI, rowId);
this.getContext().getContentResolver().notifyChange(noteUri, null);
return noteUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = mDBHelper.getWritableDatabase();
int count;
String Id;
switch (uriMatcher.match(uri)) {
case MESSAGES:
count = db.delete(Messages.TABLE_NAME, selection, selectionArgs);
break;
case MESSAGES_ID:
Id = uri.getPathSegments().get(1);
count = db.delete(Messages.TABLE_NAME, Messages._ID + "=" + Id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db = mDBHelper.getWritableDatabase();
int count;
String Id;
switch (uriMatcher.match(uri)) {
case MESSAGES:
count = db.update(Messages.TABLE_NAME, values, selection, selectionArgs);
break;
case MESSAGES_ID:
Id = uri.getPathSegments().get(1);
count = db.update(Messages.TABLE_NAME, values, Messages._ID + "=" + Id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
}
------------------------------------------------------------------------------
DBOperation.java
------------------------------------------------------------------------------
public class DBOperation {
private static final String TAG = "DBOperation";
private static final int MAX_ITEM = 200;
public static void addMessage(Context context, String message) {
ContentResolver contentResolver = context.getContentResolver();
Uri uri = DBContext.Messages.CONTENT_URI;
ContentValues contentValues = new ContentValues();
String[] projection = new String[] { "message_string" };
String selection = DBContext.Messages.MESSAGE_STRING + "=?";
Cursor cursor = contentResolver.query(uri, projection, selection, new String[] { message }, null);
//cursor.moveToFirst();
if (!cursor.moveToFirst()) {
contentValues.put(Messages.MESSAGE_STRING, message);
contentValues.put(Messages.MESSAGE_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
contentResolver.insert(uri, contentValues);
if (contentResolver.query(uri, projection, null, null, null).getCount() > MAX_ITEM) {
projection = new String[] { "min(message_timestamp) as min_timestamp" };
cursor = contentResolver.query(uri, projection, null, null, null);
cursor.moveToFirst();
String min_timestamp = cursor.getString(0);
String where = DBContext.Messages.MESSAGE_TIMESTAMP + "=?";
contentResolver.delete(uri, where, new String[] { min_timestamp });
}
} else {
String where = DBContext.Messages.MESSAGE_STRING + "=?";
message = cursor.getString(cursor.getColumnIndex(DBContext.Messages.MESSAGE_STRING));
contentValues.clear();
contentValues.put(Messages.MESSAGE_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
contentResolver.update(uri, contentValues, where, new String[] { message });
}
}
public static ArrayList<String> getAllMessages(Context context) {
ContentResolver contentResolver = context.getContentResolver();
Uri uri = DBContext.Messages.CONTENT_URI;
String[] messages = new String[] { "message_string" };
Cursor cursor = contentResolver.query(uri, messages, null, null, null);
cursor.moveToFirst();
ArrayList<String> messagesList = new ArrayList<String>();
while (!cursor.isAfterLast()) {
messagesList.add(cursor.getString(cursor.getColumnIndexOrThrow(DBContext.Messages.MESSAGE_STRING)));
cursor.moveToNext();
}
cursor.close();
return messagesList;
}
}