好的我有一个多选ListView工作正常。我检查联系人的框(保存在String []中)并可以返回值。因为有些人有一堆联系我想创建一个搜索栏,有点像Android手机书的库存。我创建了一个EditText并将其对齐在我的列表上方。我在StackOverflow上找到了过滤代码,它运行得非常好。
我的问题:
当您对某些人的名称进行过滤,并选择名称时,如果从EditText退格或继续键入,则不会保存所选名称的正确位置。例如,如果我开始键入“Adam”并进入“Ada”并选择它,如果我退格键入“Carol”,则选择“Ada”所处的位置。它收集了“亚当”在点击时所处的位置(比方说2),当列表恢复时,检查位置(2),即使亚当不在那里。我需要一种方法来收集名称..然后当再次恢复或搜索列表时,将检查NAME Adam,而不是之前的位置Adam亚当。除了创建大量数组之外,我绝对没有任何想法,并且可以真正使用一些帮助。以下是我正在使用的一些代码:
@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);
}
};
答案 0 :(得分:10)
我从未找到比我下面列出的方法更好的方法。我不再使用这个代码了,如果有更好的解决方案,我希望有人将它发布到某处。
我最终做的是创建一个ArrayList
来保存所选名称。如果选择了名称,则名称将被推送到ArrayList
,如果未选中,则会从列表中弹出。选择afterTextChanged
时,将遍历列表并检查名称是否当前在适配器中列出。当您完成选择过程并想继续时,我清除EditText
以清除过滤器,因此在ListView中填充完整列表并将所有联系人设置为选中(如果它们存在于ArrayList中)。
注意,我使用自定义适配器作为仅列出名称的联系人列表,因此如果您使用其他类型的数据,此解决方案可能会更加混乱,我将此方法视为黑客解决方案:
/** 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
使用过滤器时不想使用索引,因为索引1可能在一个ListView
中,而在更改过滤器时可能是另一个ListView
项。
答案 1 :(得分:4)
你可以创建android项目并添加这些文件:
RES /布局 - &GT; 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 /布局 - &GT; 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>