Search code examples
androidlistviewsearchhighlightspannable

searchview result in listview, but not highlight the result


I have created a searchview, when i type a word and press ENTER from the keyboard, the results show on a listview in 3 or 4 seconds. so i want to insert a progres spinner till the result populated. And Also I want to try to highlight the search word in the result in list view. I use "SpannableString highlightKeyword" but unable to highlight the result search word, I have tried many ways followed by several websites, but nothing happend. I Couldn't figure out where the mistake. Here are My codes: mainactivity.java :

  public class MainActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {

// Declare Variables
ListView list;
ListViewAdapter adapter;
SearchView editsearch;
String[] animalNameList;
ArrayList<AnimalNames> arraylist = new ArrayList<AnimalNames>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    Resources res = getResources();

    String[] animalNameList = res.getStringArray(R.array.animalNameList);



    // Locate the ListView in listview_main.xml
    list = (ListView) findViewById(R.id.listview);

    for (int i = 0; i < animalNameList.length; i++) {
        AnimalNames animalNames = new AnimalNames(animalNameList[i]);
        // Binds all strings into an array
        arraylist.add(animalNames);
    }

    // Pass results to ListViewAdapter Class
    adapter = new ListViewAdapter(this, arraylist);

    // Binds the Adapter to the ListView
    list.setAdapter(adapter);

    // Locate the EditText in listview_main.xml
    editsearch = (SearchView) findViewById(R.id.search);
    editsearch.setOnQueryTextListener(this);

}

@Override
    public boolean onQueryTextSubmit(String newText) {
    String text = newText;
    adapter.filter(text);

    return false;
}

@Override
public boolean onQueryTextChange(String newText) {

    return false;
}

===== ListviewAdapter.java:

  public class ListViewAdapter extends BaseAdapter {

// Declare Variables

Context mContext;
LayoutInflater inflater;
private List<AnimalNames> animalNamesList = null;
private ArrayList<AnimalNames> arraylist;

public ListViewAdapter(Context context, List<AnimalNames> animalNamesList) {
    mContext = context;
    this.animalNamesList = animalNamesList;
    inflater = LayoutInflater.from(mContext);
    this.arraylist = new ArrayList<AnimalNames>();
    this.arraylist.addAll(animalNamesList);
}

public class ViewHolder {
    TextView name;
}

@Override
public int getCount() {
    return animalNamesList.size();
}

@Override
public AnimalNames getItem(int position) {
    return animalNamesList.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.listview_item, null);
        // Locate the TextViews in listview_item.xml
        holder.name = (TextView) view.findViewById(R.id.name);
        view.setTag(holder);
    } else {
        holder = (ViewHolder) view.getTag();
    }

    // Set the results into TextViews
    holder.name.setText(animalNamesList.get(position).getAnimalName());


    return view;
}


// Filter Class
public void filter(String charText) {
    charText = charText.toLowerCase(Locale.getDefault());
    animalNamesList.clear();
    if (charText.length() == 0) {
        animalNamesList.addAll(arraylist);
    } else {
        for (AnimalNames wp : arraylist) {
            if (wp.getAnimalName().toLowerCase(Locale.getDefault()).contains(charText)) {
                animalNamesList.add(wp);
            }
        }
    }
    notifyDataSetChanged();
}


////Here My problem starts : 

public static SpannableString highlightKeyword(CharSequence text, Pattern p, int fgcolor, int bgcolor) {
    SpannableString ss = new SpannableString(text);

    ColorStateList blueColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{Color.BLUE});

    int start = 0;
    int end;
    Matcher m = p.matcher(text);
    while (m.find(start)) {
        start = m.start();
        end = m.end();

        BackgroundColorSpan bgspan = new BackgroundColorSpan(bgcolor);
        ss.setSpan(bgspan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        ForegroundColorSpan fgspan = new ForegroundColorSpan(fgcolor);
        ss.setSpan(fgspan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        start = end;
    }

    return ss;
}


////But even did not the result word highlighted. 

Thanks in Advance.


Solution

  • Alhamdulillah, At last I found my answer on google. Highligh in custom adapter within getview() method. As follows :

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        TextView text;
    
        if (convertView == null) {
            view = mInflater.inflate(R.layout.list_item, null);
        } else {
            view = convertView;
        }
    
        try {
            if (mFieldId == 0) {
                //  If no custom field is assigned, assume the whole resource is a TextView
                text = (TextView) view;
            } else {
                //  Otherwise, find the TextView field within the layout
                text = (TextView) view.findViewById(mFieldId);
            }
        } catch (ClassCastException e) {
            Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
            throw new IllegalStateException(
                    "ArrayAdapter requires the resource ID to be a TextView", e);
        }
    
        // HIGHLIGHT...
    
    
    
        String fullText = getItem(position);
        if (mSearchText != null && !mSearchText.isEmpty()) {
            int startPos = fullText.toLowerCase(Locale.US).indexOf(mSearchText.toLowerCase(Locale.US));
            int endPos = startPos + mSearchText.length();
    
            if (startPos != -1) {
                Spannable spannable = new SpannableString(fullText);
                ColorStateList blueColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{Color.BLUE});
                TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, blueColor, null);
                spannable.setSpan(highlightSpan, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                text.setText(spannable);
    
            } else {
                text.setText(fullText);
                 }
        } else {
            text.setText(fullText);
    
    
        }
    
    
        return view;
    }