Filtering Custom Adapter Returning Incorrect Results
Solution 1:
Your problems come from the way you setup the getView()
method and how you set the checked item in that SparseBooleanArray. I've edited your adapter's code and it should work now. The main changes are in the OnCheckedChangeListener
field:
publicclassMyCustomAdapterextendsBaseAdapterimplementsFilterable {
private Context mContext;
private LayoutInflater mInflater;
private SparseBooleanArray mSparseBooleanArray;
// from where do you get the data?private ArrayList<Map<String, String>> mAdapData = newArrayList<Map<String, String>>();
private ArrayList<Map<String, String>> mOriginalData = newArrayList<Map<String, String>>();
publicMyCustomAdapter(Context mContext) {
mInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSparseBooleanArray = newSparseBooleanArray();
}
public ArrayList<String> getCheckedItems() {
ArrayList<String> mTempArry = newArrayList<String>();
for (inti=0; i < mAdapData.size(); i++) {
if (mSparseBooleanArray.get(i)) {
Map<String, String> map = (Map<String, String>) mAdapData
.get(i);
finalStringnumbr= map.get("Phone");
mTempArry.add(numbr);
}
}
return mTempArry;
}
@OverridepublicintgetCount() {
returnthis.mAdapData.size();
}
publicvoidaddItem(String paramString1, String paramString2) {
Map<String, String> NameNumber = newHashMap<String, String>();
NameNumber.put("Name", paramString1);
NameNumber.put("Phone", paramString2);
mAdapData.add(NameNumber);
mOriginalData.add(NameNumber);
notifyDataSetChanged();
}
@SuppressWarnings("unchecked")public Object getItem(int paramInt) {
return (ArrayList<Map<String, String>>) this.mAdapData.get(paramInt);
}
@OverridepubliclonggetItemId(int paramInt) {
return paramInt;
}
@Overridepublic View getView(finalint paramInt, View paramView,
ViewGroup paramViewGroup) {
ViewHolder viewHolder;
if (paramView == null) {
viewHolder = newViewHolder();
paramView = mInflater.inflate(R.layout.adapters_specialfilterrow,
paramViewGroup, false);
viewHolder.tvName = (TextView) paramView
.findViewById(R.id.textView1);
viewHolder.tvNumber = (TextView) paramView
.findViewById(R.id.textView2);
viewHolder.cb = (CheckBox) paramView.findViewById(R.id.checkBox1);
paramView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) paramView.getTag();
}
viewHolder.cb.setTag(paramInt);
viewHolder.cb.setOnCheckedChangeListener(null);
viewHolder.cb.setChecked(mSparseBooleanArray.get(paramInt));
viewHolder.cb.setOnCheckedChangeListener(mCheckedChangeListener);
viewHolder.tvName.setTextColor(Color.BLACK);
viewHolder.tvNumber.setTextColor(Color.BLACK);
Map<String, String> map = (Map<String, String>) mAdapData.get(paramInt);
finalStringname= map.get("Name");
finalStringnumbr= map.get("Phone");
viewHolder.tvName.setText(name);
viewHolder.tvNumber.setText(numbr);
return paramView;
}
OnCheckedChangeListenermCheckedChangeListener=newOnCheckedChangeListener() {
publicvoidonCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// get the item from the current mAdapData
Map<String, String> item = mAdapData.get((Integer) buttonView
.getTag());
intposition= -1;
// see where is the item placed in the mOriginalData and use that// positionfor (inti=0; i < mOriginalData.size(); i++) {
final Map<String, String> tmp = mOriginalData.get(i);
if (tmp.get("Name").toLowerCase().equals(item.get("Name").toLowerCase())) {
position = i;
break;
}
}
mSparseBooleanArray.put(position, isChecked);
}
};
publicstaticclassViewHolder {
TextView tvName;
TextView tvNumber;
CheckBox cb;
}
@Overridepublic Filter getFilter() {
returnnewMyContactFilter();
}
@SuppressLint("DefaultLocale")privateclassMyContactFilterextendsFilter {
@Overrideprotected FilterResults performFiltering(CharSequence constraint) {
FilterResultsresults=newFilterResults();
ArrayList<Map<String, String>> mFilteredData = newArrayList<Map<String, String>>();
if (!TextUtils.isEmpty(constraint)) {
for (inti=0; i < mAdapData.size(); i++) {
Map<String, String> map = (Map<String, String>) mAdapData
.get(i);
finalStringnames= map.get("Name");
finalStringnumbr= map.get("Phone");
if (names.toLowerCase().contains(
constraint.toString().toLowerCase())) {
Map<String, String> FilNameNumber = newHashMap<String, String>();
FilNameNumber.put("Name", names);
FilNameNumber.put("Phone", numbr);
mFilteredData.add(FilNameNumber);
}
}
results.values = mFilteredData;
results.count = mFilteredData.size();
} else {
synchronized (mOriginalData) {
results.values = mOriginalData;
results.count = mOriginalData.size();
}
}
return results;
}
@SuppressWarnings("unchecked")@OverrideprotectedvoidpublishResults(CharSequence cs, FilterResults fr) {
mAdapData = (ArrayList<Map<String, String>>) fr.values;
notifyDataSetChanged();
}
}
}
Solution 2:
I have also implemented filter List View in my application. For that, I just need a snippet of code. Check it, if it helps.
editText.addTextChangedListener(new TextWatcher() {
publicvoidonTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
publicvoidbeforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
}
publicvoidafterTextChanged(Editable arg0) {
sendToList.this.adapter.getFilter().filter(arg0);
}
});
Solution 3:
in the getView()
method , you didn't update the UI to have the values of the filtered results .
so it returned views with old results .
just before return paramView , update the view's data to what you have in the filtered results , and remove it from the preparation of the viewHolder , since this is called only a few times .
EDIT: here's my correction of the code . i think it will fix it:
@OverridepublicViewgetView(final int paramInt, View paramView, ViewGroup paramViewGroup) {
ViewHolder viewHolder;
if (paramView == null) {
viewHolder = newViewHolder();
paramView = mInflater.inflate(R.layout.multiplecontactview, null);
viewHolder.tvName = (TextView) paramView.findViewById(R.id.txtContactName);
viewHolder.tvNumber = (TextView) paramView.findViewById(R.id.txtContactNumber);
viewHolder.cb = (CheckBox) paramView.findViewById(R.id.checkBox1);
viewHolder.tvName.setTextColor(Color.BLACK);
viewHolder.tvNumber.setTextColor(Color.BLACK);
paramView.setTag(viewHolder);
viewHolder.cb.setOnCheckedChangeListener(mCheckedChangeListener);
} else {
viewHolder = (ViewHolder) paramView.getTag();
}
viewHolder.cb.setTag(paramInt);
viewHolder.cb.setChecked(mSparseBooleanArray.get(paramInt));
Map<String, String> map = (Map<String, String>) mAdapData.get(paramInt);
final String name = map.get("Name").toString();
Log.e("Name", name);
final String numbr = map.get("Phone").toString();
Log.e("Number", numbr);
viewHolder.tvName.setText(name);
viewHolder.tvNumber.setText(numbr);
return paramView;
}
EDIT: here's a sample of how i handled the filtering :
@Overridepublic Filter getFilter()
{
final Filter filter=new Filter()
{
@Overrideprotected FilterResults performFiltering(final CharSequence constraint)
{
_lastFilterConstraint=constraint;
if(TextUtils.isEmpty(constraint))
returnnull;
final String constraintToCheck=constraint.toString().toLowerCase(Locale.getDefault());
final FilterResults results=new FilterResults();
// <- here i do the filtering itself and later put the results into "results"
results.values=values;
results.count=values.size();
return results;
}
@SuppressWarnings("unchecked")@Overrideprotected void publishResults(final CharSequence constraint,final FilterResults results)
{
_filteredItems==null ? null : (ArrayList<Item>)results.values;
notifyDataSetChanged();
}
};
return filter;
}
@Overridepublic int getCount()
{
if(_filteredItems!=null)
return _filteredItems.size();
return _originalItems.size();
}
@Overridepublic Item getItem(final int position)
{
if(_filteredItems!=null)
{
if(position<_filteredItems.size())
return _filteredItems.get(position);
returnnull;
}
if(position<_originalItems.size())
return _originalItems.get(position);
returnnull;
}
@Overridepublic View getView(final int position,final View convertView,final ViewGroup parent)
{
final View inflatedView;
final ViewHolder viewHolder;
if(convertView==null)
{
//<- here i inflate the view into the inflatedView
}
else
{
inflaterView=convertView;
viewHolder=(ViewHolder)inflaterView.getTag();
}
// <- here i use getItem and update the view according to its data .return inflaterView;
}
Post a Comment for "Filtering Custom Adapter Returning Incorrect Results"