Reputation: 15
I wanted to add a search function that filters the ListView
and show only the results so I added an EditText
and I added to it a TextWatcher
and wrote this code MainActivity.this.adapter.getFilter().filter(cs);
but it doesn't work it says "Cannot resolve getFilter method" and I do get the fact that there isn't an getFilter
method in my BaseAdapter but I don't know how to do it or what I should write and I saw a couple of tutorials but I can't maake it work with my code.
P.S: the ListView
items are gathered from the internet they are not saved in the app code
Here is MainActivity:
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private InterstitialAd interstitial;
// Navigation drawer title
private CharSequence mDrawerTitle;
private CharSequence mTitle;
private List<Category> albumsList;
private ArrayList<NavDrawerItem> navDrawerItems;
private NavDrawerListAdapter adapter;
private LinearLayout DrawerLinear;
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("Test", "OnCreate Called");
mTitle = mDrawerTitle = getTitle();
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.list_slidermenu);
DrawerLinear = (LinearLayout) findViewById(R.id.DrawerLinear);
navDrawerItems = new ArrayList<NavDrawerItem>();
// Getting the albums from shared preferences
albumsList = AppController.getInstance().getPrefManger().getCategories();
// Insert "Recently Added" in navigation drawer first position
Category recentAlbum = new Category(null,
getString(R.string.nav_drawer_recently_added));
albumsList.add(0, recentAlbum);
// Loop through albums in add them to navigation drawer adapter
for (Category a : albumsList) {
navDrawerItems.add(new NavDrawerItem(a.getId(), a.getTitle()));
}
mDrawerList.setOnItemClickListener(new SlideMenuClickListener());
// Setting the nav drawer list adapter
adapter = new NavDrawerListAdapter(getApplicationContext(),
navDrawerItems);
mDrawerList.setAdapter(adapter);
// Enabling action bar app icon and behaving it as toggle button
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
getActionBar().setIcon(
new ColorDrawable(getResources().getColor(
android.R.color.transparent)));
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.app_name, R.string.app_name) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
// calling onPrepareOptionsMenu() to show action bar icons
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
// calling onPrepareOptionsMenu() to hide action bar icons
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
// on first time display view for first nav item
displayView(0);
}
final EditText inputSearch = (EditText) findViewById(R.id.inputSearch);
inputSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
//You should use the adapter in NavigationDrawerFragment
MainActivity.this.adapter.getFilter().filter(cs); // Doesn't work, gives an error "Cannot resolve getFilter method"
}
@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
}
});
}
and here is my Adapter:
public class NavDrawerListAdapter extends BaseAdapter{
private Context context;
private ArrayList<NavDrawerItem> navDrawerItems;
public NavDrawerListAdapter(Context context,
ArrayList<NavDrawerItem> navDrawerItems) {
this.context = context;
this.navDrawerItems = navDrawerItems;
}
@Override
public int getCount() {
return navDrawerItems.size();
}
@Override
public Object getItem(int position) {
return navDrawerItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.drawer_list_item, null);
}
TextView txtTitle = (TextView) convertView.findViewById(R.id.title);
txtTitle.setText(navDrawerItems.get(position).getTitle());
return convertView;
}
}
Upvotes: 1
Views: 2105
Reputation: 508
You can add a SearchView in your toolbar/actionbar in order to let the user search(filter) the listview. Here an example (http://javapapers.com/android/android-searchview-action-bar-tutorial/). Then you can filter using a Filterable adapter following what Danail Alexiev suggested to you or simply filtering the source of the adapter and updating the adapter from outside.
Upvotes: 0
Reputation: 1626
First you should implement your adapter from Filterable
public class NavDrawerListAdapter extends BaseAdapter implements Filterable
and override getFilter method:
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence searchText) {
//by searchText you should filter here
FilterResults result = new FilterResults();
// here your filtering
// filling result
return result;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
// here your filterResults
clear();
addAll(filterResults.values);
notifyDataSetChanged();
}
};
}
Second in your Activity declare Filter object
private Filter filter;
in onCreate initialize filter:
adapter = new NavDrawerListAdapter(getApplicationContext(),
navDrawerItems);
// getting filter from adapter
filter = adapter.getFilter();
and in your onTextChanged:
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
//You should use the adapter in NavigationDrawerFragment
filter.filter(cs);
}
Thats all:)
Upvotes: 0
Reputation: 7792
You should implement the Filterable
interface in your custom adapter. It is not implemented by BaseAdapter.
Edit: This is a more complete example:
public class FiltarableAdapter extends BaseAdapter implements Filterable {
// keep the full data here. This is needed to not loose it while filtering
private List<SomeObject> originalData;
// keep the data you want to show to the user here
private List<SomeObject> data;
// skip adapter methods
// we will use an instance of this to perform the filtering
private class AdapterFilter implements Filter {
FilterResults performFiltering(CharSequence constraint) {
// use the constraint to filter your data in this method and create a list containing the result
List<SomeObject> filteredData = ...
FilterResults result = new FilterResults();
result.count = filteredData.size();
result.object = filteredData;
}
void publishResults(CharSequence constraint, Filter.FilterResults results) {
// here you get the search results and you should use them to update your UI
// for brevity of the example, we just replace the current adapter data with the result object
FilterableAdapter.this.data = results.object;
FilterableAdapter.this.notifyDataSetChanged();
}
}
public Filter getFilter() {
return new AdapterFilter();
}
}
Basically, you define your filter internally in the adapter and return a new instance to the client that calls getFilter()
. In the filter itself you need to do the search in your data and, when you have the results, swap the resulting data set with the current data set. You will need to keep the original unfiltered data set as well, so you are able to quickly restore the list if the filter is cleared.
Hope this helps.
Upvotes: 3