多select可search的ListView

好吧,我有一个多选ListView,工作正常。 我检查的联系方式(保存在一个string[]),并可以返回罚款罚款。 因为有些人有很多联系人,所以我想创build一个search栏,就像Android电话簿中的一个。 我创build了一个EditText并将其排列在我的列表上方。 我在StackOverflow上find了这个过滤代码,它工作起来非常棒。

我的问题:

当您过滤某些名称并select名称时,如果从EditText退格或继续input,则不会保存所选名称的正确位置。 例如,如果我开始input“Adam”并select“Ada”并select它,如果我退格键入“Carol”,则select“Ada”所处的位置。 它从点击(比方说2)收集“Adam”的位置,当列表恢复时,检查该位置(2),即使Adam不在那里。 我需要一种方法来收集名称..然后当列表被恢复或重新search,名称亚当被检查,而不是位置亚当以前在。 除了创build大量的数组之外,我绝对没有任何想法,并且真的可以使用一些帮助。 以下是我使用的一些代码:

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.contacts_list); myListView = (ListView)findViewById(android.R.id.list); search_EditText = (EditText) findViewById(R.id.search_EditText); search_EditText.addTextChangedListener(filterTextWatcher); adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, ContactsList); setListAdapter(adapter); myListView.setItemsCanFocus(false); getListView().setChoiceMode(2); myListView.setTextFilterEnabled(true); myListView.setFastScrollEnabled(true); myListView.invalidate(); } private TextWatcher filterTextWatcher = new TextWatcher() { public void afterTextChanged(Editable s) { } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { adapter.getFilter().filter(s); } }; 

Solutions Collecting From Web of "多select可search的ListView"

我从来没有find比我将在下面列出的方法更好的方法。 我不再使用这个代码了,如果有更好的解决scheme,我希望有人把它发布到某个地方。

我最终做的是创build一个ArrayList来保存选定的名称。 如果名称被选中,名字被压入ArrayList ,如果未选中,则从列表中popup。 当select了afterTextChanged ,列表将迭代并检查名称是否当前列在适配器中。 当您完成select过程并想要继续时,我清除EditText以清除filter,因此在ListView中填充完整列表,并将所有联系人设置为选中(如果它们存在于ArrayList中)。

注意,我使用一个自定义适配器来列出只列出名字的联系人列表,所以如果你使用其他types的数据,这个解决scheme可能会变得更加混乱,我把这种方法看作是一个被黑的解决scheme:

 /** Used for filter **/ private TextWatcher filterTextWatcher = new TextWatcher() { public void beforeTextChanged(CharSequence s, int start, int count, int after) { ListView listview = getListView(); SparseBooleanArray checked = listview.getCheckedItemPositions(); for (int i = 0; i < ContactsList.length; i++) { if (checked.get(i) == true) { Object o = getListAdapter().getItem(i); String name = o.toString(); // if the arraylist does not contain the name, add it if (selected.contains(name)){ // Do Nothing } else { selected.add(name); } } } } //<-- End of beforeTextChanged public void onTextChanged(CharSequence s, int start, int before, int count) { adapter.getFilter().filter(s); } //<-- End of onTextChanged public void afterTextChanged(Editable s) { ListView listview = getListView(); // Uncheck everything: for (int i = 0; i < listview.getCount(); i++){ listview.setItemChecked(i, false); } adapter.getFilter().filter(s, new Filter.FilterListener() { public void onFilterComplete(int count) { adapter.notifyDataSetChanged(); ListView listview = getListView(); for (int i = 0; i < adapter.getCount(); i ++) { // if the current (filtered) // listview you are viewing has the name included in the list, // check the box Object o = getListAdapter().getItem(i); String name = o.toString(); if (selected.contains(name)) { listview.setItemChecked(i, true); } else { listview.setItemChecked(i, false); } } } }); } //<-- End of afterTextChanged }; //<-- End of TextWatcher 

在使用filter时,您不希望使用索引,因为索引1可能是一个ListView中的某个东西,当您更改filter时,它可能是另一个ListView项目。

你可以创buildandroid项目并添加这些文件:

RES /布局 – > list_row.xml

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#3c3c3c" android:orientation="horizontal" android:padding="8dp" > <ImageView android:id="@+id/contactimage" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginRight="8dp" android:background="@drawable/ic_launcher" android:contentDescription="@string/app_name" android:scaleType="centerInside" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_toLeftOf="@+id/contactcheck" android:layout_toRightOf="@+id/contactimage" > <TextView android:id="@+id/contactname" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:text="Contact Name" android:textColor="#000" android:textIsSelectable="false" android:textSize="18dp" android:textStyle="bold" /> <TextView android:id="@+id/contactno" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/contactname" android:singleLine="true" android:text="09876543210" android:textColor="#2689e0" android:textIsSelectable="false" android:textSize="14dp" /> </RelativeLayout> <CheckBox android:id="@+id/contactcheck" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerInParent="true" android:layout_marginLeft="8dp" /> </RelativeLayout> 

RES /布局 – > activity_main.xml中

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <EditText android:id="@+id/input_search" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerInParent="true" android:hint="Search Contacts" android:textSize="18dp" /> <LinearLayout android:id="@+id/data_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/ok_button" android:layout_below="@+id/input_search" android:gravity="center|top" android:orientation="vertical" /> <Button android:id="@+id/ok_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerInParent="true" android:text=" OK " android:textSize="18dp" /> <RelativeLayout android:id="@+id/pbcontainer" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#55000000" android:clickable="true" android:visibility="gone" > <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> </RelativeLayout> </RelativeLayout> 

ContactObject.java

 package com.multiselectlistexample; public class ContactObject { private String contactName; private String contactNo; private String image; private boolean selected; public String getName() { return contactName; } public void setName(String contactName) { this.contactName = contactName; } public String getNumber() { return contactNo; } public void setNumber(String contactNo) { this.contactNo = contactNo; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } public boolean isSelected() { return selected; } public void setSelected(boolean selected) { this.selected = selected; } } 

ContactsListClass.java

 package com.multiselectlistexample; import java.util.ArrayList; public class ContactsListClass { public static final ArrayList<ContactObject> phoneList = new ArrayList<ContactObject>(); } 

ContactsAdapter.java

 package com.multiselectlistexample; import java.io.ByteArrayInputStream; import java.util.ArrayList; import java.util.List; import java.util.Locale; import android.content.ContentUris; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.provider.ContactsContract.Contacts; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.TextView; public class ContactsAdapter extends BaseAdapter { Context mContext; LayoutInflater inflater; private List<ContactObject> mainDataList = null; private ArrayList<ContactObject> arraylist; public ContactsAdapter(Context context, List<ContactObject> mainDataList) { mContext = context; this.mainDataList = mainDataList; inflater = LayoutInflater.from(mContext); this.arraylist = new ArrayList<ContactObject>(); this.arraylist.addAll(mainDataList); } static class ViewHolder { protected TextView name; protected TextView number; protected CheckBox check; protected ImageView image; } @Override public int getCount() { return mainDataList.size(); } @Override public ContactObject getItem(int position) { return mainDataList.get(position); } @Override public long getItemId(int position) { return position; } public View getView(final int position, View view, ViewGroup parent) { final ViewHolder holder; if (view == null) { holder = new ViewHolder(); view = inflater.inflate(R.layout.list_row, null); holder.name = (TextView) view.findViewById(R.id.contactname); holder.number = (TextView) view.findViewById(R.id.contactno); holder.check = (CheckBox) view.findViewById(R.id.contactcheck); holder.image = (ImageView) view.findViewById(R.id.contactimage); view.setTag(holder); view.setTag(R.id.contactname, holder.name); view.setTag(R.id.contactno, holder.number); view.setTag(R.id.contactcheck, holder.check); holder.check .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton vw, boolean isChecked) { int getPosition = (Integer) vw.getTag(); mainDataList.get(getPosition).setSelected( vw.isChecked()); } }); } else { holder = (ViewHolder) view.getTag(); } holder.check.setTag(position); holder.name.setText(mainDataList.get(position).getName()); holder.number.setText(mainDataList.get(position).getNumber()); if(getByteContactPhoto(mainDataList.get(position).getImage())==null){ holder.image.setImageResource(R.drawable.ic_launcher); }else{ holder.image.setImageBitmap(getByteContactPhoto(mainDataList.get(position).getImage())); } holder.check.setChecked(mainDataList.get(position).isSelected()); return view; } public void filter(String charText) { charText = charText.toLowerCase(Locale.getDefault()); mainDataList.clear(); if (charText.length() == 0) { mainDataList.addAll(arraylist); } else { for (ContactObject wp : arraylist) { if (wp.getName().toLowerCase(Locale.getDefault()) .contains(charText)) { mainDataList.add(wp); } } } notifyDataSetChanged(); } public Bitmap getByteContactPhoto(String contactId) { Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(contactId)); Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY); Cursor cursor = mContext.getContentResolver().query(photoUri, new String[] {Contacts.Photo.DATA15}, null, null, null); if (cursor == null) { return null; } try { if (cursor.moveToFirst()) { byte[] data = cursor.getBlob(0); if (data != null) { return BitmapFactory.decodeStream( new ByteArrayInputStream(data)); } } } finally { cursor.close(); } return null; } } 

MainActivity.java

 package com.multiselectlistexample; import java.util.Collections; import java.util.Comparator; import java.util.Locale; import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.Toast; public class MainActivity extends Activity { Context context = null; ContactsAdapter objAdapter; ListView lv = null; EditText edtSearch = null; LinearLayout llContainer = null; Button btnOK = null; RelativeLayout rlPBContainer = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = this; setContentView(R.layout.activity_main); rlPBContainer = (RelativeLayout) findViewById(R.id.pbcontainer); edtSearch = (EditText) findViewById(R.id.input_search); llContainer = (LinearLayout) findViewById(R.id.data_container); btnOK = (Button) findViewById(R.id.ok_button); btnOK.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub getSelectedContacts(); } }); edtSearch.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) { // When user changed the Text String text = edtSearch.getText().toString() .toLowerCase(Locale.getDefault()); objAdapter.filter(text); } @Override public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable arg0) { // TODO Auto-generated method stub } }); addContactsInList(); } private void getSelectedContacts() { // TODO Auto-generated method stub StringBuffer sb = new StringBuffer(); for (ContactObject bean : ContactsListClass.phoneList) { if (bean.isSelected()) { sb.append(bean.getName()); sb.append(","); } } String s = sb.toString().trim(); if (TextUtils.isEmpty(s)) { Toast.makeText(context, "Select atleast one Contact", Toast.LENGTH_SHORT).show(); } else { s = s.substring(0, s.length() - 1); Toast.makeText(context, "Selected Contacts : " + s, Toast.LENGTH_SHORT).show(); } } private void addContactsInList() { // TODO Auto-generated method stub Thread thread = new Thread() { @Override public void run() { showPB(); try { Cursor phones = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); try { ContactsListClass.phoneList.clear(); } catch (Exception e) { } while (phones.moveToNext()) { String phoneName = phones .getString(phones .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); String phoneNumber = phones .getString(phones .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); String phoneImage = phones .getString(phones .getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)); ContactObject cp = new ContactObject(); cp.setName(phoneName); cp.setNumber(phoneNumber); cp.setImage(phoneImage); ContactsListClass.phoneList.add(cp); } phones.close(); lv = new ListView(context); lv.setLayoutParams(new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); runOnUiThread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub llContainer.addView(lv); } }); Collections.sort(ContactsListClass.phoneList, new Comparator<ContactObject>() { @Override public int compare(ContactObject lhs, ContactObject rhs) { return lhs.getName().compareTo( rhs.getName()); } }); objAdapter = new ContactsAdapter(MainActivity.this, ContactsListClass.phoneList); lv.setAdapter(objAdapter); lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { CheckBox chk = (CheckBox) view .findViewById(R.id.contactcheck); ContactObject bean = ContactsListClass.phoneList .get(position); if (bean.isSelected()) { bean.setSelected(false); chk.setChecked(false); } else { bean.setSelected(true); chk.setChecked(true); } } }); } catch (Exception e) { e.printStackTrace(); } hidePB(); } }; thread.start(); } void showPB() { runOnUiThread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub rlPBContainer.setVisibility(View.VISIBLE); edtSearch.setVisibility(View.GONE); btnOK.setVisibility(View.GONE); } }); } void hidePB() { runOnUiThread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub rlPBContainer.setVisibility(View.GONE); edtSearch.setVisibility(View.VISIBLE); btnOK.setVisibility(View.VISIBLE); } }); } } 

AndroidManifest.xml中

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.multiselectlistexample" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <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=".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>