问题
I am tying to implement search functionality in my app. I am using a custom ArrayAdapter<String>
for the listview
as I have two textViews
in a row. My app doesn't force close but the search is not working properly. It is not filtering the listview but when I type something that is not there in the listview, it shows the no item found page properly. What could be wrong? Here is the code. Please guide me to the correct path!
MainActivity.java
public class MainActivity extends Activity {
final String[] elename ={"Hydrogen","Helium","Lithium","Beryllium","Boron","Carbon","Nitrogen","Oxygen","Fluorine","Neon","Sodium","Magnesium","Aluminium","Silicon","Phosphorous","Sulphur","Chlorine","Argon","Potassium","Calcium","Scandium","Titanium","Vanadium","Chromium","Manganese","Iron","Cobalt","Nickel","Copper","Zinc","Gallium","Germanium","Arsenic","Selenium","Bromine","Krypton","Rubidium","Strontium","Yttrium","Zirconium","Niobium","Molybdenum","Technetium","Ruthenium","Rhodium","Palladium","Silver","Cadmium","Indium","Tin","Antimony","Tellurium","Iodine","Xenon","Caesium","Barium","Lanthanum","Cerium","Praseodymium","Neodymium","Promethium","Samarium","Europium","Gadolinium","Terbium","Dysprosium","Holmium","Erbium","Thulium","Ytterbium","Lutetium","Hafnium","Tantalum","Tungsten","Rhenium","Osmium","Iridium","Platinum","Gold","Mercury","Thallium","Lead","Bismuth","Polonium","Astatine","Radon","Francium","Radium","Actinium","Thorium","Protactinium","Uranium","Neptunium","Plutonium","Americium","Curium","Berkelium","Californium","Einsteinium","Fermium","Mendelevium","Nobelium","Lawrencium","Rutherfordium","Dubnium","Seaborgium","Bohrium","Hassium","Meitnerium","Darmstadtium","Roentgenium","Copernicium","Ununtrium","Ununquadium","Ununpentium","Ununhexium","Ununseptium","Ununoctium"};
final String[] nos = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70","71","72","73","74","75","76","77","78","79","80","81","82","83","84","85","86","87","88","89","90","91","92","93","94","95","96","97","98","99","100","101","102","103","104","105","106","107","108","109","110","111","112","113","114","115","116","117","118"};
CustomAdapter cus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText searchBar = (EditText) findViewById(R.id.searchbar);
final DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
final ListView navList = (ListView) findViewById(R.id.left_drawer);
final LinearLayout linearLayout = (LinearLayout)findViewById(R.id.left_drawer_layout);
cus = new CustomAdapter(MainActivity.this,elename,nos);
navList.setAdapter(cus);
navList.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, final int pos,long id){
//Change view according to numbers
drawer.closeDrawer(linearLayout);
}
});
//filter list view after search instantly
searchBar.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
MainActivity.this.cus.getFilter().filter(cs);
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,int arg3) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
//hide the keyboard after search on touch list view
navList.setOnScrollListener(new AbsListView.OnScrollListener() {
public void onScrollStateChanged(AbsListView view, int scrollState) {
//hide keyboard
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(navList.getWindowToken(), 0);
}
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
navList.setEmptyView(findViewById(R.id.empty));
}
}
CustomAdapter.java
class CustomAdapter extends ArrayAdapter<String>
{
String A[],B[];
LayoutInflater mInflater;
public CustomAdapter(Context context, String[] A,String B[])
{
super(context,R.layout.list_item,A);
this.A = A;
this.B = B;
mInflater = LayoutInflater.from(context);
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null)
{
convertView = mInflater.inflate(R.layout.list_item,parent,false);
holder = new ViewHolder();
holder.tv1 = (TextView)convertView.findViewById(R.id.element_name);
holder.tv2 = (TextView)convertView.findViewById(R.id.element_nos);
convertView.setTag(holder);
}else{
holder = (ViewHolder)convertView.getTag();
}
holder.tv1.setText(A[position]);
holder.tv2.setText(B[position]);
return convertView;
}
static class ViewHolder
{
TextView tv1,tv2;
}
}
EDIT: App force closing after the implementation of interface.
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.Chinmay.navigationdrawer/com.Chinmay.navigationdrawer.MainActivity}: java.lang.ClassCastException: com.Chinmay.navigationdrawer.MainActivity
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassCastException: com.Chinmay.navigationdrawer.MainActivity
at com.Chinmay.navigationdrawer.MainActivity.onCreate(MainActivity.java:49)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
回答1:
Add this cus.setSearchFilterItemListener(this);
before navList.setAdapter(cus);
Update
Step 1 Create an interface
public interface SearchFilterItemListener {
public void setData(String[] myArray);
}
Step 2 Update your custom adapter class
class CustomAdapter extends ArrayAdapter<String> {
String A[], B[], origA[], origB[];
LayoutInflater mInflater;
public CustomAdapter(Context context, String[] A,String B[]) {
super(context, R.layout.list_item, A);
this.A = A;
this.B = B;
this.origA = A;
this.origB = B;
mInflater = LayoutInflater.from(context);
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.tv1 = (TextView)convertView.findViewById(R.id.element_name);
holder.tv2 = (TextView)convertView.findViewById(R.id.element_nos);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.tv1.setText(A[position]);
holder.tv2.setText(B[position]);
return convertView;
}
static class ViewHolder {
TextView tv1,tv2;
}
@Override
public Filter getFilter() {
if (listFilter == null)
listFilter = new TabFilter();
return listFilter;
}
private class TabFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
// TODO Auto-generated method stub
FilterResults results = new FilterResults();
// Filter Logic
if (constraint == null || constraint.length() == 0) {
// No filter, return all the list
results.values = origA; //considering that you want to filter on the String[] A
results.count = origA.size();
} else {
// We perform filtering operation
String[] nList = new String[A.length];
for (int counter = 0; counter < A.length; counter++) {
if (A[counter].toUpperCase(Locale.US).startsWith(constraint.toString().toUpperCase(Locale.US)))
nList[counter] = A[counter];
}
results.values = nList;
results.count = nList.length;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// TODO Auto-generated method stub
// Now we have to inform the adapter about the new filtered list
if (results.count == 0)
notifyDataSetInvalidated();
else {
A = (String[]) results.values;
String[] newList = new String[A.length];
newList = A.clone();
notifyDataSetChanged();
mSearchListener.setData(newList);
}
}
}
public String[] getSearchList() {
return A;
}
public void setSearchFilterItemListener(SearchFilterItemListener mSearchFilterListener) {
mSearchListener = mSearchFilterListener;
}
}
回答2:
ok so this is your adapter:
class CustomAdapter extends ArrayAdapter<Item> {
LayoutInflater mInflater;
public CustomAdapter(Context context) {
super(context, 0);
mInflater = LayoutInflater.from(context);
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
convertView = mInflater.inflate(android.R.layout.simple_expandable_list_item_2, parent, false);
holder = new ViewHolder();
holder.tv1 = (TextView)convertView.findViewById(android.R.id.text1);
holder.tv2 = (TextView)convertView.findViewById(android.R.id.text2);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
Item item = getItem(position);
holder.tv1.setText(item.text1);
holder.tv2.setText(item.text2);
return convertView;
}
}
now you have Item class holding two Strings:
class Item {
String text1;
String text2;
Item(String t1, String t2) {
text1 = t1;
text2 = t2;
}
@Override
public String toString() {
return text1;
}
}
and the ViewHolder:
class ViewHolder {
TextView tv1, tv2;
}
now test it in onCreate (try to press any letter, "p" for example to filter out thos items starting with "p":
CustomAdapter adapter = new CustomAdapter(this);
for (int i = 0; i < elename.length; i++) {
adapter.add(new Item(elename[i], nos[i]));
}
lv = new ListView(this);
lv.setTextFilterEnabled(true);
lv.setAdapter(adapter);
setContentView(lv);
来源:https://stackoverflow.com/questions/21383747/listview-filtering-not-working-android