package com.llamacorp.equate.view; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Filter; import android.widget.Filterable; import android.widget.TextView; import com.llamacorp.equate.R; import java.util.ArrayList; import java.util.LinkedHashSet; /** * Custom adapter class that implements the Filterable interface, allowing it * to filter items within it based on a filter string. */ class FilterAdapter extends BaseAdapter implements Filterable { private ArrayList<UnitSearchItem> mArrayList; // current values post filtering private ArrayList<UnitSearchItem> mOriginalValues; // values pre filtering private LayoutInflater inflater; FilterAdapter(Context context, ArrayList<UnitSearchItem> arrayList) { this.mArrayList = arrayList; inflater = LayoutInflater.from(context); } @Override public int getCount() { return mArrayList.size(); } @Override public Object getItem(int position) { return position; } public UnitSearchItem getUnitSearchItem(int position) { return mArrayList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null){ holder = new ViewHolder(); convertView = inflater.inflate(R.layout.filter_dialog_list_row, parent, false); holder.mNameTextView = (TextView) convertView.findViewById(R.id.search_dialog_name_textView); holder.mAbbreviationTextView = (TextView) convertView.findViewById(R.id.search_dialog_abbreviation_textView); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } String s = mArrayList.get(position).getUnitName(); holder.mNameTextView.setText(s); holder.mAbbreviationTextView.setText(mArrayList.get(position).getUnitAbbreviation()); return convertView; } @Override public Filter getFilter() { return new Filter() { @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { mArrayList = (ArrayList<UnitSearchItem>) 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 /* Create a hierarchy or order results separated by different sets * and then added together at the end. Note HashSet used to guarantee * no duplicate results */ LinkedHashSet<UnitSearchItem> list1 = new LinkedHashSet<>(); LinkedHashSet<UnitSearchItem> list2 = new LinkedHashSet<>(); LinkedHashSet<UnitSearchItem> list3 = new LinkedHashSet<>(); LinkedHashSet<UnitSearchItem> list4 = new LinkedHashSet<>(); LinkedHashSet<UnitSearchItem> list5 = new LinkedHashSet<>(); if (mOriginalValues == null){ mOriginalValues = new ArrayList<>(mArrayList); // saves the original data in mOriginalValues } // if constraint is too short: if (constraint == null || constraint.length() == 0){ // set the Original result to return results.count = mOriginalValues.size(); results.values = mOriginalValues; // constraint is long enough, proceed: } else { constraint = constraint.toString().toLowerCase(); int mTextLength = constraint.length(); searchItemLoop: for (UnitSearchItem item : mOriginalValues) { String abbrev = item.getUnitAbbreviation().toLowerCase(); String longName = item.getUnitName().toLowerCase(); String data = longName + " " + abbrev; // don't proceed if the filter is longer than the item if (mTextLength > data.length()) continue; // check if the abbreviation is an exact match if (constraint.equals(abbrev)){ list1.add(item); continue; } // check if the long name is an exact match if (constraint.equals(longName)){ list2.add(item); continue; } // filter results that should appear start with constraint if (data.startsWith(constraint.toString())){ list3.add(item); continue; } // next add results that have multiple words with non-first // starting letter String dataArray[] = data.split(" "); for (String part : dataArray) { // remove all brackets if (part.replaceAll("\\(|\\)", "") .startsWith(constraint.toString())){ list4.add(item); continue searchItemLoop; } } // finally find matches within words if (data.contains(constraint)){ list5.add(item); } } // join lists preserving hierarchy and guaranteeing uniqueness list1.addAll(list2); list1.addAll(list3); list1.addAll(list4); list1.addAll(list5); results.count = list1.size(); results.values = new ArrayList<>(list1); } return results; } }; } private class ViewHolder { TextView mNameTextView; TextView mAbbreviationTextView; } }