在我的应用程序中,我正在从用户的电话簿中读取联系人,并根据用户的需求执行一些操作。从用户电话簿中导入联系人的 Activity 还包含一个 editText 字段,用户可以使用该字段过滤联系人并搜索联系人。代码如下:
public class InviteFriendsFromContactsActivity extends Activity implements
TextWatcher {
private EditText friendSearch;
private ArrayList<ContactInfo> contacts;
private ListView contactsListView;
private ContactsListviewAdapter clvAdapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.invite_from_contacts);
friendSearch = (EditText) findViewById(R.id.friendsearch);
friendSearch.addTextChangedListener(this);
contactsListView = (ListView) findViewById(R.id.ContactsListView);
ReadContacts();
}
void ReadContacts() {
contacts = new ArrayList<ContactInfo>();
Cursor cursor = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
while (cursor.moveToNext()) {
long contactId = cursor.getLong(cursor
.getColumnIndex(ContactsContract.Contacts._ID));
String name = cursor.getString(cursor
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Cursor emails = getContentResolver().query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = "
+ contactId, null, null);
while (emails.moveToNext()) {
// This would allow to get several email addresses, so if 1
// contact has 2 emails, will be listed as 2 rows
String emailAddress = emails
.getString(emails
.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
if (emailAddress != null)
contacts.add(new ContactInfo(contactId, name, emailAddress));
}
emails.close();
}
cursor.close();
clvAdapter = new ContactsListviewAdapter(getApplicationContext(),
contacts);
contactsListView.setAdapter(clvAdapter);
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (clvAdapter != null) {
clvAdapter.getFilter().filter(s);
contactsListView.setAdapter(clvAdapter);
}
if (clvAdapter.getCount() == 0) {
ListView list = (ListView) findViewById(R.id.ContactsListView);
list.setClickable(false);
final List<ContactInfo> listItems = new ArrayList<ContactInfo>();
listItems.add(new ContactInfo("No results", ""));
ContactsListviewAdapter adapter = new ContactsListviewAdapter(
InviteFriendsFromContactsActivity.this, listItems) {
@Override
public View getView(int position, View convertView,
ViewGroup viewGroup) {
ContactInfo entry = listItems.get(position);
CheckBox checkBox;
TextView nameText;
TextView emailText;
LayoutInflater inflater = (LayoutInflater) InviteFriendsFromContactsActivity.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row, null);
nameText = (TextView) convertView
.findViewById(R.id.toptext);
emailText = (TextView) convertView
.findViewById(R.id.bottomtext);
checkBox = (CheckBox) convertView
.findViewById(R.id.checkBox_invited);
checkBox.setVisibility(View.GONE);
nameText.setText(entry.getName());
emailText.setVisibility(View.GONE);
convertView.setBackgroundColor(Color.WHITE);
return convertView;
}
};
list.setAdapter(adapter);
}
}
}
另外,我的 ContactsListViewAdapter 类如下。这是一个相当大的课程,但我认为与这个问题最相关的部分是getFilter
方法。
class ContactsViewHolder {
public ContactsViewHolder(TextView nameTextView, TextView emailTextView,
CheckBox checkBox, ImageView iv) {
super();
this.nameTextView = nameTextView;
this.emailTextView = emailTextView;
this.checkBox = checkBox;
this.iv = iv;
}
public TextView getNameTextView() {
return nameTextView;
}
public void setNameTextView(TextView nameTextView) {
this.nameTextView = nameTextView;
}
public TextView getEmailTextView() {
return emailTextView;
}
public void setEmailTextView(TextView emailTextView) {
this.emailTextView = emailTextView;
}
public CheckBox getCheckBox() {
return checkBox;
}
public void setCheckBox(CheckBox checkBox) {
this.checkBox = checkBox;
}
public ImageView getIv() {
return iv;
}
public void setIv(ImageView iv) {
this.iv = iv;
}
private TextView nameTextView;
private TextView emailTextView;
private CheckBox checkBox;
private ImageView iv;
}
public class ContactsListviewAdapter extends BaseAdapter implements Filterable {
private Context context;
private List<ContactInfo> contacts;
private List<ContactInfo> originalContacts;
private List<String> selectedEmails = new ArrayList<String>();
public ContactsListviewAdapter(Context context, List<ContactInfo> contacts) {
this.context = context;
this.contacts = contacts;
}
public int getCount() {
return contacts.size();
}
public Object getItem(int position) {
return contacts.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup viewGroup) {
ContactInfo entry = contacts.get(position);
CheckBox checkBox;
TextView nameText;
TextView emailText;
ImageView contactPic;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row, null);
nameText = (TextView) convertView.findViewById(R.id.toptext);
emailText = (TextView) convertView.findViewById(R.id.bottomtext);
contactPic = (ImageView) convertView.findViewById(R.id.pic);
checkBox = (CheckBox) convertView
.findViewById(R.id.checkBox_invited);
// Optimization: Tag the row with it's child views, so we don't have
// to
// call findViewById() later when we reuse the row.
convertView.setTag(new ContactsViewHolder(nameText, emailText,
checkBox, contactPic));
// If CheckBox is toggled, update the planet it is tagged with.
checkBox.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
ContactInfo contact = (ContactInfo) cb.getTag();
contact.setChecked(cb.isChecked());
if(contact.isChecked())
{
selectedEmails.add(contact.getEmail());
}
}
});
}
// Reuse existing row view
else {
// Because we use a ViewHolder, we avoid having to call
// findViewById().
ContactsViewHolder viewHolder = (ContactsViewHolder) convertView
.getTag();
checkBox = viewHolder.getCheckBox();
nameText = viewHolder.getNameTextView();
emailText = viewHolder.getEmailTextView();
contactPic = viewHolder.getIv();
}
// Tag the CheckBox with the Contact it is displaying, so that we can
// access the Contact in onClick() when the CheckBox is toggled.
checkBox.setTag(entry);
// Display contact data
checkBox.setChecked(entry.isChecked());
nameText.setText(entry.getName());
emailText.setText(entry.getEmail());
Bitmap bitmap = People.loadContactPhoto(context,
ContentUris.withAppendedId(People.CONTENT_URI, entry.getId()),
R.drawable.contacts, null);
contactPic.setImageBitmap(bitmap);
return convertView;
}
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
contacts = (List<ContactInfo>) results.values; // has the filtered values
notifyDataSetChanged(); // notifies the data with new filtered values
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults(); // Holds the
// results of a
// filtering
// operation in
// values
List<ContactInfo> FilteredArrList = new ArrayList<ContactInfo>();
if (originalContacts == null) {
originalContacts = new ArrayList<ContactInfo>(contacts);
}
/********
*
* If constraint(CharSequence that is received) is null returns
* the mOriginalValues(Original) values else does the Filtering
* and returns FilteredArrList(Filtered)
*
********/
if (constraint == null || constraint.length() == 0) {
// set the Original result to return
results.count = originalContacts.size();
results.values = originalContacts;
} else {
constraint = constraint.toString().toLowerCase();
for (int i = 0; i < originalContacts.size(); i++) {
String name = originalContacts.get(i).getName();
if (name.toLowerCase()
.startsWith(constraint.toString())) {
FilteredArrList.add(originalContacts.get(i));
}
}
// set the Filtered result to return
results.count = FilteredArrList.size();
results.values = FilteredArrList;
}
return results;
}
};
return filter;
}
public List<String> getSelectedEmails() {
return selectedEmails;
}
}
联系人在活动中导入就好了。当我尝试搜索联系人时出现问题。当我在搜索字段中输入“x”(我的电话簿中没有以 x 开头的联系人)时,显示了 0 个联系人,No results found
但未显示消息。它只会在我在“x”之后键入另一个字母后显示。通常,消息No results found
总是在实际应该显示的 1 个字母之后显示。
出了什么问题,消息是如何延迟的?