I have a custom ListView that Get baseadapter by passing xml data ArrayList.
I want to perform a search using ActionbarSherlock 4.2 Searchview, so after user puts an text and press the button it will inflate a new layout with the results.
What is the best guideline?
Custom Listview:
public class CustomizedListView extends ListFragment {
// All static variables
static final String URL = "http://api.androidhive.info/music/music.xml";
// XML node keys
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";
ListView list;
LazyAdapter adapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
songsList.add(map);
}
// Getting adapter by passing xml data ArrayList
adapter = new LazyAdapter(getActivity(), songsList);
setListAdapter(adapter);
}
}
BaseAdapter:
public class LazyAdapter extends BaseAdapter {
private FragmentActivity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public LazyAdapter(FragmentActivity fragmentActivity, ArrayList<HashMap<String, String>> d) {
activity = fragmentActivity;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_row, null);
TextView title = (TextView)vi.findViewById(R.id.title); // title
TextView artist = (TextView)vi.findViewById(R.id.artist); // artist name
TextView duration = (TextView)vi.findViewById(R.id.duration); // duration
ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
// Setting all values in listview
title.setText(song.get(CustomizedListView.KEY_TITLE));
artist.setText(song.get(CustomizedListView.KEY_ARTIST));
duration.setText(song.get(CustomizedListView.KEY_DURATION));
imageLoader.DisplayImage(song.get(CustomizedListView.KEY_THUMB_URL), thumb_image);
return vi;
}
}
Sherlock ActionBar SearchView:
public abstract class BaseSampleActivity extends SherlockFragmentActivity {
private static final Random RANDOM = new Random();
TestFragmentAdapter mAdapter;
ViewPager mPager;
PageIndicator mIndicator;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
SearchView searchView = new SearchView(getSupportActionBar().getThemedContext());
searchView.setQueryHint("Procure pelo nome");
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
Intent search = new Intent(getApplicationContext(), SearchableActivity.class);
search.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
search.putExtra(query, query);
startActivityForResult(search, 0);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
});
menu.add("Search")
.setIcon(R.drawable.ic_search_inverse)
.setActionView(searchView)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
return true;
}
The NewActivity:
public class SearchableActivity extends SherlockListActivity{
// All static variables
static final String URL = "http://api.androidhive.info/music/music.xml";
// XML node keys
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";
private String message;
private ListView list;
private LazyAdapterS adapter;
protected void onCreate(Bundle savedInstanceState, String query) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
message = getIntent().getExtras().getString(query);
setContentView(R.layout.main_list_row);
ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
songsList.add(map);
}
list=(ListView)findViewById(R.id.list);
// Getting adapter by passing xml data ArrayList
adapter = new LazyAdapterS(this, songsList);
list.setAdapter(adapter);
((Filterable) list.getAdapter()).Filter(message);// Error The method Filter(String) is undefined for the type Filterable
}
}
UPDATE: I put the setOnQueryTextListener as Suggested by @Luksprog. UPDATE: I´ve created a new Activity to show the results from the search, but still got a error on filter, I dont know how to handle this.
Thank you,
Should I implement Filterable on BaseAdapter?
If you want to use the standard filtering mechanism for an adapter(which any Android SDK adapter does), yes, you need to implement the Filterable
interface and provide a proper implementation for it's two methods.
And if yes, how I handle to get tostring() from Sherlock Searchview instead of filterText.addTextChangedListener(filterTextWatcher);?
Have a look at OnQueryTextListener
:
public boolean onQueryTextSubmit(String query) {
((Filterable) listview.getAdapter()).filter(query);
return true;
}
Should I create a new BaseAdapter to download only the listview hint by the search? And If yes, Do you have any sample or tutorial to link?
If you mean, parsing again the xml(using only what matches the query string) and create a new adapter to show the results, no because you'll be doing a lot of unnecessary work(especially all the network calls which you should really try move on a background thread).
If you want to show the results in a new activity then put the query String
in the Intent
that starts the results activity and do/redo the filtering there.
Or anyother way?
See point one.