package com.cyrilmottier.android.queryhighlight;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListView;
import android.widget.TextView;
import com.cyrilmottier.android.queryhighlight.text.Normalizer;
import com.cyrilmottier.android.queryhighlight.text.TextWatcherAdapter;
import com.cyrilmottier.android.queryhighlight.text.format.QueryHighlighter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public final class MainActivity extends AppCompatActivity {
private CheesesAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new CheesesAdapter();
final ListView listView = (ListView) findViewById(android.R.id.list);
listView.setAdapter(mAdapter);
final ActionBar actionBar = getSupportActionBar();
actionBar.setCustomView(R.layout.search_view);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
final EditText editText = (EditText) actionBar.getCustomView();
editText.addTextChangedListener(mTextWatcher);
editText.requestFocus();
}
public final class CheesesAdapter extends BaseAdapter implements Filterable {
private final QueryHighlighter mQueryHighlighter;
private final Filter mFilter;
private List<String> mCheeses;
private String mQuery;
public CheesesAdapter() {
mCheeses = Cheeses.ALL;
mFilter = new WordFilter(mCheeses);
mQueryHighlighter = new QueryHighlighter().
setQueryNormalizer(QueryHighlighter.QueryNormalizer.FOR_SEARCH);
}
@Override
public int getCount() {
return mCheeses.size();
}
@Override
public String getItem(int position) {
return mCheeses.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean isEnabled(int position) {
return false;
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.list_item_text, parent, false);
}
mQueryHighlighter.setText((TextView) convertView, getItem(position), mQuery);
return convertView;
}
// NOTE Cyril
// - ArrayAdapter has built-in filtering by default but normalization
// is only case-based.
// - CursorAdapter has built-int filtering too. However, try to favor
// restarting a query (with a Loader for instance) instead.
// - When data comes from the network, it's up to you to restart the
// query.
@Override
public Filter getFilter() {
return mFilter;
}
public void setQuery(String query) {
if (!Objects.equals(query, mQuery)) {
getFilter().filter(query);
}
}
private final class WordFilter extends Filter {
private final List<String> mItems;
private WordFilter(List<String> items) {
mItems = new ArrayList<>(items);
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
final List<String> list;
if (TextUtils.isEmpty(constraint)) {
list = mItems;
} else {
list = new ArrayList<>();
final String normalizedConstraint = Normalizer.forSearch(constraint);
for (String item : mItems) {
final String normalizedItem = Normalizer.forSearch(item);
if (normalizedItem.startsWith(normalizedConstraint) || //
normalizedItem.contains(" " + normalizedConstraint)) {
list.add(item);
}
}
}
final FilterResults results = new FilterResults();
results.values = list;
results.count = list.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//noinspection unchecked
mCheeses = (List<String>) results.values;
mQuery = constraint != null ? constraint.toString() : null;
mAdapter.notifyDataSetChanged();
}
}
}
private final TextWatcher mTextWatcher = new TextWatcherAdapter() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mAdapter.setQuery(s != null ? s.toString() : null);
}
};
}