我有一个列表视图,每行都有一个复选框,我已经实现了一个serch视图来搜索列表视图。问题是当我搜索列表视图并从修改后的列表中选择位置X处的项目时,从搜索视图中删除文本,我会看到原始列表,并在位置X中选中项目。
示例 - a,b,c .... z。
的列表我可以在列表中看到5个项目:
一个 乙 C d ë
然后搜索z所以我只看到Z并检查它。然后我删除Z并再次看到A-E并检查A.
这是我的主要内容:
public class AddRoomatesScreen extends Activity implements AdapterView.OnItemClickListener,SearchView.OnQueryTextListener {
SharedPreferences preferences;
List<String> nameList = new ArrayList<String>();
List<String> phoneList = new ArrayList<String>();
MyAdapter adapter;
Button btnSelect;
String apartmentnumber;
SearchView searchView;
ArrayList<Contact> contactList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_roomate);
preferences = getSharedPreferences("appData", 0);
int apartmentNumber = preferences.getInt("apartmentNumber", 0);
apartmentnumber = Integer.toString(apartmentNumber);
getAllContacts(this.getContentResolver());
ListView lv = (ListView) findViewById(R.id.lv);
adapter = new MyAdapter(nameList,contactList);
lv.setAdapter(adapter);
lv.setOnItemClickListener(this);
lv.setItemsCanFocus(false);
lv.setTextFilterEnabled(true);
searchView = (SearchView) findViewById(R.id.search_view);
searchView.setOnQueryTextListener(this);
// adding
btnSelect = (Button) findViewById(R.id.addSelectedContacts);
btnSelect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(int i = 0; i<adapter.mCheckStates.size(); i++){
Contact contact = (adapter.contactsListCopy.get(adapter.mCheckStates.keyAt(i)));
new addRoommate().execute(apartmentnumber, contact.getPhoneNumber());
}
preferences = getSharedPreferences("appData", 0);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("roomatesLoadedFromDB", false);
editor.apply();
}
});
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
adapter.toggle(arg2);
}
public void getAllContacts(ContentResolver cr) {
Cursor phones = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
while (phones.moveToNext()) {
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
nameList.add(name);
phoneList.add(phoneNumber);
contactList.add(new Contact(name,phoneNumber));
}
phones.close();
}
这是我的适配器:
class MyAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener,Filterable {
private SparseBooleanArray mCheckStates;
LayoutInflater mInflater;
TextView tv;
CheckBox cb;
ValueFilter filter;
ArrayList<Contact> contactsList;
ArrayList<Contact> contactsListCopy;
MyAdapter(List<String> nameList , ArrayList<Contact> contactsList) {
mCheckStates = new SparseBooleanArray(contactsList.size());
mInflater = (LayoutInflater) AddRoomatesScreen.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.contactsList = contactsList;
this.contactsListCopy = this.contactsList;
getFilter();
}
@Override
public int getCount() {
return contactsListCopy.size();
}
@Override
public Object getItem(int position) {
return contactsListCopy.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View vi = convertView;
if (convertView == null)
vi = mInflater.inflate(R.layout.contact_list_item, null);
TextView tv = (TextView) vi.findViewById(R.id.textView3);
cb = (CheckBox) vi.findViewById(R.id.checkBox);
Contact contact = contactsListCopy.get(position);
tv.setText(contact.getName());
cb.setTag(position);
cb.setChecked(mCheckStates.get(position, false));
cb.setOnCheckedChangeListener(this);
return vi;
}
public boolean isChecked(int position) {
return mCheckStates.get(position, false);
}
public void setChecked(int position, boolean isChecked) {
mCheckStates.put(position, isChecked);
notifyDataSetChanged();
}
public void toggle(int position) {
setChecked(position, !isChecked(position));
}
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mCheckStates.put((Integer) buttonView.getTag(), isChecked);
}
@Override
public Filter getFilter() {
if (filter == null){
filter = new ValueFilter();
}
return filter;
}
private class ValueFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<Contact> temp = new ArrayList<Contact>();
for (int i = 0; i < contactList.size(); i++) {
Contact c = contactList.get(i);
if ((c.getName().toString())
.contains(constraint.toString())) {
temp.add(c);
}
}
results.count = temp.size();
results.values = temp;
} else {
results.count = contactList.size();
results.values = contactList;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
contactsListCopy = (ArrayList<Contact>) results.values;
notifyDataSetChanged();
}
}
}
这是我的模特:
public class Contact{
private String phoneNumber;
private String name;
public Contact(String name , String phoneNumber){
this.phoneNumber = phoneNumber;
this.name = name;
}
public String getName() {
return name;
}
public String getPhoneNumber() {
return phoneNumber;
}
}
答案 0 :(得分:4)
编辑:
您可以使用光标中的ID作为唯一ID。
此代码将使用下面最初发布的代码。
将ID添加到您的Contact类:
public class Contact{
private long id;
private String phoneNumber;
private String name;
public Contact(long id, String name , String phoneNumber) {
this.id = id;
this.phoneNumber = phoneNumber;
this.name = name;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
public String getPhoneNumber() {
return phoneNumber;
}
}
这是从光标获取ID的方法:
public void getAllContacts(ContentResolver cr) {
Cursor phones = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
while (phones.moveToNext()) {
long id = phones.getLong(phones.getColumnIndex(ContactsContract.Data._ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
nameList.add(name);
phoneList.add(phoneNumber);
contactList.add(new Contact(id, name, phoneNumber));
}
phones.close();
}
适配器中的mCheckStates
更改为:
private LongSparseArray<Boolean> mCheckStates;
以下部分原始答案已更改为与用于ID的long
类型相匹配。
问题在于,mCheckStates
布尔地图在过滤时与contactsListCopy
保持同步。
您需要跟踪已检查的联系人,而不是跟踪已检查的位置。为此,您需要使用联系人记录中的唯一ID。
以下是您需要做出的更改:
使您的适配器使用唯一ID:
@Override
public long getItemId(int position) {
return contactsListCopy.get(position).getId();
}
现在您的活动必须使用唯一ID而不是位置:
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
adapter.toggle(arg3);
}
在适配器getView()
中,您必须使用现在复选框的ID
cb.setTag(contact.getId());
cb.setChecked(mCheckStates.get(contact.getId(), false));
为了避免混淆,我会更改其他一些方法:
public boolean isChecked(long id) {
return mCheckStates.get(id, false);
}
public void setChecked(long id, boolean isChecked) {
mCheckStates.put(id, isChecked);
notifyDataSetChanged();
}
public void toggle(long id) {
setChecked(id, !isChecked(id));
}