سؤال

I am developing an application. In which a list view is displayed in which the data is coming from SQLite data base. I am getting data in String[].

Now the need of application is that : I want to add a search bar in top of the activity. This search bar should perform search only on the list showing on the activity.

When user type a letter in search bar all the data should display in list view who is containing that letter.

I tried the following code.

In main.java

EditText search= (EditText) findViewById(R.id.edittext_searchbar);
search.addTextChangedListener(new TextWatcher() {
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    adapter.getFilter().filter(s);
        adapter.notifyDataSetChanged();
    }   
    public void beforeTextChanged(CharSequence s, int start, int count,int after) {
    }
    @Override
    public void afterTextChanged(Editable s) {
    }
    });
listView.setAdapter(adapter);

And in Adapter class :

public void setData(String[] menuList) {   
    menuListofAdapter = menuList;//contains class items data.
}

@Override
public Filter getFilter() {
    return new Filter() {
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        if (results != null && results.count >= 0) {
        setData((String[]) results.values);//if results of search is null set the searched results data
    } else {
                setData(menuListofAdapter);// set original values
            }
            notifyDataSetInvalidated();
        }

        @SuppressWarnings("null")
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults result = new FilterResults();
            if (!TextUtils.isEmpty(constraint)) {
                constraint = constraint.toString();
                String[] fItem = null;
                if(Utility.mainMenuList!=null){
                    for(int i=0,j=0;i<Utility.mainMenuList.length;i++){
                    if (Utility.mainMenuList[i].equalsIgnoreCase(constraint.toString())) {
                             fItem[j] = Utility.mainMenuList[i];
                         j=j+1;
                     }else{
                     }
                 }
             }
             result.count = fItem.length;
             result.values = fItem;
         } else{
             result.count=-1;// no search results found
         }             
         return result;
        }
     };
 }

What should i do for this. The data is in String[]. Display in list view.

Please suggest me what changes are required.

When i applied above code and run my app and tried to search, I got error as :

03-12 18:16:19.215: D/AndroidRuntime(836): Shutting down VM
03-12 18:16:19.215: W/dalvikvm(836): threadid=1: thread exiting with uncaught exception (group=0x40015560)
03-12 18:16:19.215: E/AndroidRuntime(836): FATAL EXCEPTION: main
03-12 18:16:19.215: E/AndroidRuntime(836): java.lang.ClassCastException: java.util.ArrayList
03-12 18:16:19.215: E/AndroidRuntime(836):  at com.abc.example.adapters.MyListAdapter$1.publishResults(MainMenuListAdapter.java:41)
03-12 18:16:19.215: E/AndroidRuntime(836):  at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
03-12 18:16:19.215: E/AndroidRuntime(836):  at android.os.Handler.dispatchMessage(Handler.java:99)
03-12 18:16:19.215: E/AndroidRuntime(836):  at android.os.Looper.loop(Looper.java:123)
03-12 18:16:19.215: E/AndroidRuntime(836):  at android.app.ActivityThread.main(ActivityThread.java:3683)
03-12 18:16:19.215: E/AndroidRuntime(836):  at java.lang.reflect.Method.invokeNative(Native Method)
03-12 18:16:19.215: E/AndroidRuntime(836):  at java.lang.reflect.Method.invoke(Method.java:507)
03-12 18:16:19.215: E/AndroidRuntime(836):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
03-12 18:16:19.215: E/AndroidRuntime(836):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
03-12 18:16:19.215: E/AndroidRuntime(836):  at dalvik.system.NativeStart.main(Native Method)
هل كانت مفيدة؟

المحلول

Have a editext at the top of your listview. I suggest you to have a custom list adapter.

Have a list of original values for database.

Have another list to set temporary data to match the search criteria.

If your search criteria matches one in the list add those to founditmes and display the data in the list. If it does not match display original data in the list.

I have given a general idea. The below code can be modified according to your needs. I have implemented the search myself and it works.

I asked a question in SO and i got the answer from How to implement search in CustomListView based on class item of POJO class in Android?.

Try the below and if you are not able to get it working you can always post a question in SO.

     search= (EditText) findViewById(R.id.search);
     //look for text changing in edittext.
     search.addTextChangedListener(new TextWatcher() {

         public void onTextChanged(CharSequence s, int start, int before, int count) {
                         youradapter.getFilter().filter(s);
                         youradapter.notifyDataSetChanged();

         }

         public void beforeTextChanged(CharSequence s, int start, int count,
             int after) {


           }

           public void afterTextChanged(Editable s) {
           }
          });

Implement a filter on your list

 public void setData(ArrayList mPpst) {   
         set data either searched data or original values from database
        mPostingData = mPpst;//contains class items data.
    }

 @Override
 public Filter getFilter() {
     return new Filter() {
         @Override
         protected void publishResults(CharSequence constraint, FilterResults results) {
             if (results != null && results.count >= 0) {
                 setData( results.values);//if results match set data
             } else {
                 setData(mOri);// set data for listview original values.
             }

             notifyDataSetInvalidated();
         }



        @Override
         protected FilterResults performFiltering(CharSequence constraint) {
             FilterResults result = new FilterResults();
             if (!TextUtils.isEmpty(constraint)) {
                   ArrayList foundItems = new ArrayList();
                 constraint = constraint.toString().toLowerCase();
                 if(listitems!=null)
                 {
                         if(listitems.equals(constarint))//matching
                         foundItems.add(listitems);

                     }
                     else
                     {

                     }
                 }
                 }
                 result.count = foundItems.size();//search results found return count
                 result.values = foundItems;// return values
             } 
             else
             {
                 result.count=-1;// no search results found
             }


             return result;
         }
     };
 }

Edit 1

how to set json parsed data in a listview and then adding search functionality in it. The answer in the link works. I have used temporary data and did a search function on it. You can display data form database and modify the same.

Edit 2:

 public class MainActivity extends Activity {

// List view
private ListView lv;

// Listview Adapter
ArrayAdapter<String> adapter;

// Search EditText
EditText inputSearch;


// ArrayList for Listview
ArrayList<HashMap<String, String>> productList;

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

    // Listview Data
    String products[] = {"aaa","bbbb","cccc","dddd"};

    lv = (ListView) findViewById(R.id.list_view);
    inputSearch = (EditText) findViewById(R.id.inputSearch);

    // Adding items to listview
    adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.product_name, products);
    lv.setAdapter(adapter);

    /**
     * Enabling Search Filter
     * */
    inputSearch.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            // When user changed the Text
            MainActivity.this.adapter.getFilter().filter(cs);   
        }

        @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                          
        }
    });
  }

}

Edit 3 Search with data from Database

 public class SearchActivity extends ListActivity {
 ArrayAdapter<String> dataAdapter = null;

  private ArrayList<String> results = new ArrayList<String>();
  private String tableName = DatabaseHandler.TABLE_SEARCH;
  private SQLiteDatabase newDB;
  ArrayAdapter<String> adapter = null;

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

   DatabaseHandler dbHelper = new DatabaseHandler(this.getApplicationContext());
   newDB = dbHelper.getWritableDatabase();
   Cursor c = newDB.rawQuery("SELECT skeys FROM " +
        tableName, null);
   if (c != null ) {
    if  (c.moveToFirst()) {
        do {
            String skeys = c.getString(c.getColumnIndex("skeys"));
            results.add(skeys);
        }while (c.moveToNext());
    } 
 }           

dataAdapter = new ArrayAdapter<String>(this,
        R.layout.listviews_search, results);

setListAdapter(new ArrayAdapter<String>(this,
        R.layout.listviews_search, results));

  ListView listView = (ListView) findViewById(android.R.id.list);
  listView.setAdapter(dataAdapter);
  listView.setTextFilterEnabled(true);

  listView.setOnItemClickListener(new OnItemClickListener() {
      public void onItemClick(AdapterView<?> parent, View view,
              int position, long id) {
          Toast.makeText(getApplicationContext(),
                  ((TextView) view).getText(), Toast.LENGTH_SHORT).show();
      }
  });

  EditText myFilter = (EditText) findViewById(R.id.search);
  myFilter.addTextChangedListener(new TextWatcher(){
      public void afterTextChanged(Editable s) {
  }

      public void beforeTextChanged(CharSequence s, int start, int count, int after) {
  }

      public void onTextChanged(CharSequence s, int start, int before, int count) {
   dataAdapter.getFilter().filter(s.toString());
      }
  });
 }
}

نصائح أخرى

For your requirement you have to use Sectioned List view in android. Please see this link. http://samir-mangroliya.blogspot.in/2012/05/android-sectioned-listview-with-search_6865.html. It will help you alot.Let me know you have any doubts.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top