【Android】利用AutoCompleteTextView控件联系人自动补全与根据联系人姓名查询电话

自动补全功能是app比较友好的功能之一,但利用AutoCompleteTextView自动补全文本框控件完成起来并不简单,因为其中涉及到AutoCompleteTextView填充数据的适配器,与AutoCompleteTextView的监听器。同时还需要利用ContentResolver去查找设备的通讯录,当然,这与《【Android】利用安卓的数据接口、多媒体处理编写内存卡Mp3播放器app》(点击打开链接)中遍历MP3与《【Android】Sqlite数据库增删改查》(点击打开链接)中遍历Sqlite数据库是一样的。下面举一个小例子,说明AutoCompleteTextView的使用:

【Android】利用AutoCompleteTextView控件联系人自动补全与根据联系人姓名查询电话_第1张图片

如上图,假设在用户手机中有3个联系人,现在有一个能自动补全的文本框,输入完名字,自动显示其在通讯录的电话。如果没有则给出相应的信息。

制作过程如下:

1、首先res\values\strings.xml字体文件,没什么好说:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">自动补全联系人与寻找其电话</string>
    <string name="action_settings">Settings</string>
    <string name="textView1">姓名:</string>

</resources>

2、之后是res\layout\activity_main.xml中的布局修改。一个垂直的线性布局中间放一个水平的线性布局,使TextView1与自动完成的文本框处于一行。之后一个显示结果的TextView2赋予id,此处的autoCompleteTextView1设定android:completionThreshold="1",是指用户输入1个字符就开始给出补全信息了。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/textView1"
            android:textSize="24sp" />

        <AutoCompleteTextView
            android:id="@+id/autoCompleteTextView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:completionThreshold="1" />
    </LinearLayout>

    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="24sp" />

</LinearLayout>

3、在AndroidManifest.xml申请读取联系人的权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.autocomplete"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <uses-permission android:name="android.permission.READ_CONTACTS" /><!-- 要求读取通讯录 -->

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.autocomplete.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>
    </application>

</manifest>

4、MainActivity.java才是本app的重点,里面包含autoCompleteTextView自动文本框的适配器,用来填充数据的。数据是通过ContentResolver去查安卓设备中的联系人表查出来的姓名信息。之后,MainActivity本身实现TextWatcher接口,用来作为autoCompleteTextView自动文本框的监听器,当前用户选择自动补全的选项或者自己输入数据,都会给触发TextWatcher监听。根据联系人查询电话的时候,是需要同时对安卓中固有的两张表进行操作,一张是用户设备中的联系人姓名表,一张是与联系人姓名表同id排列的联系人电话表。具体代码具体如下:

package com.autocomplete;

import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.support.v4.widget.CursorAdapter;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.FilterQueryProvider;
import android.widget.Filterable;
import android.widget.TextView;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;

//autoCompleteTextView自动文本框的适配器
class ContactListAdapter extends CursorAdapter implements Filterable {

	private ContentResolver resolver;
	private String[] columns = new String[] { Contacts._ID,
			Contacts.DISPLAY_NAME };// 一会儿,游标查询出来的表就两列,一列是id,一列是联系人姓名

	public ContactListAdapter(Context context, Cursor c, int flags) {
		// 调用父类构造方法,此处ContactListAdapter(Context context, Cursor
		// c)方法已经过时,多出了一个参数flags
		// 其实都没有什么用,flags扔个0给它就OK
		super(context, c, flags);
		resolver = context.getContentResolver();// 初始化ContentResolver
	}

	// 这里要自己形成一个下拉菜单
	@Override
	public void bindView(View view, Context arg1, Cursor cursor) {
		((TextView) view).setText(cursor.getString(1));
	}

	@Override
	public View newView(Context context, Cursor cursor, ViewGroup parent) {
		LayoutInflater inflater = LayoutInflater.from(context);
		TextView view = (TextView) inflater.inflate(
				android.R.layout.simple_dropdown_item_1line, parent, false);
		view.setText(cursor.getString(1));// 各项项的文字,就是游标查询出来的,联系人姓名那一列
		return view;
	}

	@Override
	public CharSequence convertToString(Cursor cursor) {
		return cursor.getString(1);
	}

	@Override
	public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
		FilterQueryProvider filter = getFilterQueryProvider();
		if (filter != null) {
			return filter.runQuery(constraint);
		}
		// 这里是指明游标的查询的表,与查询结果列
		Uri uri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
				Uri.encode(constraint.toString()));
		return resolver.query(uri, columns, null, null, null);
	}
}

public class MainActivity extends Activity implements TextWatcher {
	private AutoCompleteTextView autoCompleteTextView1;
	private TextView textView2;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// 注册组件
		autoCompleteTextView1 = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
		textView2 = (TextView) findViewById(R.id.textView2);
		// 构造autoCompleteTextView的适配器
		ContentResolver contentResolver = getContentResolver();
		String[] colmuns = new String[] { Contacts._ID, Contacts.DISPLAY_NAME };
		Cursor cursor = contentResolver.query(Contacts.CONTENT_URI, colmuns,
				null, null, null);
		ContactListAdapter contactListAdapter = new ContactListAdapter(this,
				cursor, 0);
		// 指明autoCompleteTextView的适配器与监听器
		autoCompleteTextView1.setAdapter(contactListAdapter);
		autoCompleteTextView1.addTextChangedListener(this);

	}

	// 根据联系人的姓名查询电话
	private String getQueryData(String name) {
		String phoneNum = "";
		// 查联系人姓名这张表,有无用户输入的姓名
		ContentResolver contentResolver1 = getContentResolver();
		String[] colmuns1 = new String[] { Contacts._ID, Contacts.DISPLAY_NAME };
		Cursor cursor1 = contentResolver1.query(Contacts.CONTENT_URI, null,
				null, null, null);
		for (cursor1.moveToFirst(); !(cursor1.isAfterLast()); cursor1
				.moveToNext()) {
			String contactsName = cursor1.getString(cursor1
					.getColumnIndex(colmuns1[1]));
			// 如果有,则开始查联系人电话这张表
			if (name.equals(contactsName)) {
				int id = cursor1.getInt(cursor1.getColumnIndex(colmuns1[0]));
				ContentResolver contentResolver2 = getContentResolver();
				String[] colmuns2 = new String[] { Phone.CONTACT_ID,
						Phone.NUMBER };
				// 查询的联系人电话这张表时候,加入一个条件,就查目录联系人姓名那列数据中的id
				// 由于联系人电话这张表与联系人姓名这张表是同id的
				// 查询参数放在第三个参数这个位置
				Cursor cursor2 = contentResolver2.query(Phone.CONTENT_URI,
						null, colmuns2[0] + "=" + id, null, null);
				if (cursor2.moveToNext()) {// 如果Cursor中有数据,要把初始位置为0的Cursor下拉一位才能拿到数据
					phoneNum = cursor2.getString(cursor2
							.getColumnIndex(colmuns2[1]));

				}
			}
		}
		return phoneNum;// 查到就返回相应的电话,没查到就扔回0
	}

	// autoCompleteTextView自动文本框的监听器,果断是等信息完完整整地摆到文本框才是查找
	@Override
	public void afterTextChanged(Editable arg0) {
		String name = autoCompleteTextView1.getText() + "";
		String phoneNum = getQueryData(name);
		if (phoneNum.equals("")) {
			textView2.setText("无此联系人!");
		} else {
			textView2.setText("电话为:" + phoneNum);
		}

	}

	@Override
	public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
			int arg3) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub

	}

}


你可能感兴趣的:(安卓,监听,自动补全,联系人)