Android filter listview custom adapter
Asked Answered
V

6

1

Hello everybody I'm doing an app which has an edittext to search for items on the listview. If the user types a letter. The data come from my json string (database) and then display on my listview. So far this is what I've tried:

 ListViewAdapter adapter2;
 ArrayList<HashMap<String, String>> arraylist;
 ArrayList<String> list = new ArrayList<String>();

 wsSearch.addTextChangedListener(new TextWatcher (){

        public void afterTextChanged(Editable cs) {
            // TODO Auto-generated method stub



        }

        public void beforeTextChanged(CharSequence arg0, int arg1,
                int arg2, int arg3) {
            // TODO Auto-generated method stub

        }

        public void onTextChanged(CharSequence cs, int arg1, int arg2,
                int arg3) {
            // TODO Auto-generated method stub
            //BAPTISMAL_SONG.this.adapter2.getFilter().filter(cs); 


            String searchString = cs.toString();
            if(searchString.length() != 2) {
                adapter2 = new ListViewAdapterBaptismal(BAPTISMAL_SONG.this, arraylist);
                listview.setAdapter(adapter2);
                return;
            }
            ArrayList<HashMap<String, String>> arrayTemplist = new ArrayList<HashMap<String,String>>();
            for (int i = 0; i < arraylist.size(); i++)
                {
                String currentString = arraylist.get(i).get(BAPTISMAL_SONG.TAG_TITLE);
                if (searchString.equalsIgnoreCase(currentString))
                    {
                        arrayTemplist.add(arraylist.get(i));
                    }
                }
            adapter2 = new ListViewAdapterBaptismal(BAPTISMAL_SONG.this, arrayTemplist);
            listview.setAdapter(adapter2);

        }

    });

@Override
protected void onPostExecute(Void args) {
        // Locate the listview in listview_main.xml

        // Pass the results into ListViewAdapter.java
        adapter2 = new ListViewAdapter(Activity2.this, arraylist);
        // Binds the Adapter to the ListView
        listview.setAdapter(adapter2);


        // Close the progressdialog
        mProgressDialog.dismiss();
    }
}

What I want to achieve, if the user types a letter like B, all the items that start with the said letter should be filtered. But using the code I posted above, it does not do exactly what I want. It just filters whenever I typed the whole item name. Any ideas? Your help will be greatly appreciated. Thanks.

Verbosity answered 31/1, 2014 at 8:49 Comment(2)
Maybe this is what you need:developer.android.com/reference/android/widget/… ?Sled
look at this example androidbegin.com/tutorial/…Wadi
L
1

As far as I can see you are only checking if the two Strings match exactly. You might want to use boolean startsWith(String prefix)

Which would make something like

if (currentString.trim().toLowerCase().startsWith(searchString.trim().toLowerCase()))
{
     arrayTemplist.add(arraylist.get(i));
} 
Lunular answered 31/1, 2014 at 8:58 Comment(6)
I tried this, but when I type the exact item name it does not filter.Verbosity
try using trim() on the searchString and currentString. I edited my answer.Lunular
Still the same, when I type letter T, it displays all items that start with that letter but when I type another letter again it's reverting back to the original list. And also I changed my code like your updated one, i tried to type the whole item name it's not filtering.Verbosity
I think because the block "if(searchString.length() != 2) {". What do you want here. (Please do not create ListViewAdapterBaptismal instance for each search string change)Savitt
You should also get rid of the if(searchString.length() != 2) part. If you don't type exactly two characters, the whole list is shown.Lunular
Whoa my bad, I removed it, and it's working fine now. Thanks!Verbosity
C
1

I got complete solution, i put filter method in custom adapter for multiple fields search functionality.

Note: for image loading i took lazy loading so you need ImageLoader.java, FileCache.java, Utils.java and MemoryCache.java.

Check bellow code.....

list_layout.xml ( layout folder )

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    android:background="#ffffff" >

    <EditText 
         android:id="@+id/et_search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="search...."
        android:paddingLeft="5dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" 

        />
    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_marginTop="5dp"
        android:layout_height="match_parent"
       android:layout_below="@+id/et_search">
    </ListView>

</RelativeLayout>

custom_row.xml ( layout folder )

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#33B5E5" >

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginBottom="23dp"
        android:layout_marginLeft="23dp"
        android:layout_marginTop="23dp"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/txt_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/image_view"
        android:layout_marginLeft="15dp"
        android:layout_toRightOf="@+id/image_view"
        android:text="id"
        android:textColor="#ffffff" />

    <TextView
        android:id="@+id/txt_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/txt_id"
        android:layout_below="@+id/txt_id"
        android:text="name"
        android:textColor="#ffffff" />

</RelativeLayout>

put sample.json file in assets folder

sample.json

{
   "sample":[
      {
         "id":"1",
         "name":"nirav kalola",
         "image":"http://www.wallpaperfunda.com/wp-content/uploads/2014/03/images-2.jpg",
         "description":"def"
      },
      {
         "id":"2",
         "name":"abc",
         "image":"http://www.wallpaperfunda.com/wp-content/uploads/2014/03/images-2.jpg",
         "description":"abc"
      },
      {
         "id":"3",
         "name":"def",
         "image":"http://www.wallpaperfunda.com/wp-content/uploads/2014/03/images-2.jpg",
         "description":"ghi"
      },
      {
         "id":"55",
         "name":"ghi",
         "image":"http://www.wallpaperfunda.com/wp-content/uploads/2014/03/images-2.jpg",
         "description":"jkl"
      },
      {
         "id":"5",
         "name":"jkl",
         "image":"http://www.wallpaperfunda.com/wp-content/uploads/2014/03/images-2.jpg",
         "description":"mno"
      },
      {
         "id":"11",
         "name":"mno",
         "image":"http://www.wallpaperfunda.com/wp-content/uploads/2014/03/images-2.jpg",
         "description":"pqr"
      },
      {
         "id":"10",
         "name":"nirav007",
         "image":"http://www.wallpaperfunda.com/wp-content/uploads/2014/03/images-2.jpg",
         "description":"stu"
      }
   ]
}

ListActivity.java ( src folder )

public class ListActivity extends Activity {

    private ListView listView;
    private ProgressDialog progressDialog;
    private List<SampleData> sampleData;
    private ArrayList<SampleData> sampleList;
    private SampleAdapter sampleAdapter;
    private EditText etSearch;

    ArrayList<SampleData> arraylist = new ArrayList<SampleData>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_layout);
        listView=(ListView) findViewById(R.id.list_view);

        BackGroundTask bt = new BackGroundTask();
        bt.execute();
        etSearch=(EditText) findViewById(R.id.et_search);
        etSearch.setSingleLine(true);


        etSearch.addTextChangedListener(new TextWatcher() {

            public void afterTextChanged(Editable s) {
                String text = etSearch.getText().toString().toLowerCase(Locale.getDefault()); 
                sampleAdapter.filter(text);

            }

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

            }

            public void onTextChanged(CharSequence s, int start, int before,
                    int count) {

            }   
        });
    }

    private class BackGroundTask extends AsyncTask<Void, Void, String> {


        @Override
        protected void onPreExecute(){
            super.onPreExecute();
            progressDialog = new ProgressDialog(ListActivity.this);
            progressDialog.setCancelable(false);
            progressDialog.setMessage("Loading...");
            progressDialog.show();   
        }

        @Override
        protected String doInBackground(Void... arg0) {
            try {
                JSONObject jsonObject = new JSONObject(loadJSONFromAsset());
                JSONArray jsonArray = jsonObject.getJSONArray("sample");
                sampleData=new ArrayList<SampleData>();

                for (int i = 0; i < jsonArray.length(); i++) 
                {
                    JSONObject jsonObjectInside = jsonArray.getJSONObject(i);

                    String id = jsonObjectInside.getString("id");
                    String name = jsonObjectInside.getString("name");
                    String imagePath = jsonObjectInside.getString("image");
                    String description = jsonObjectInside.getString("description");
                    sampleData.add(new SampleData(id, name, imagePath, description));           
                    Log.e("id",id+"");
                    Log.e("name",name+"");
                    Log.e("imagPath",imagePath+"");
                    Log.e("description",description+"");

                }

                handlePostsList(sampleData);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 

            return null;
        }


        @Override
        protected void onPostExecute(String result){
            super.onPostExecute(result);
            progressDialog.dismiss();
        }  
    }// End of Background AsyncTask


    private void handlePostsList(final List<SampleData> sampleData) {
        this.sampleData = sampleData;
        runOnUiThread(new Runnable() {
            public void run() {
                try {
                    // logic for retrieve data first time in list view.
                    sampleList = new ArrayList<SampleData>();

                    for (int i = 0; i < sampleData.size(); i++) {

                        sampleList.add(new SampleData(sampleData.get(i).getId().toString(),sampleData.get(i).getName().toString(),sampleData.get(i).getImage().toString(),sampleData.get(i).getDescription().toString()));
                    }

                    sampleAdapter= new SampleAdapter(ListActivity.this, sampleList);
                    listView.setAdapter(sampleAdapter);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }


    public class SampleAdapter extends BaseAdapter
    {
        Context context;
        List<SampleData> sampleData=null;
        ArrayList<SampleData> arraylist;
        LayoutInflater inflater;
        ImageLoader imageLoader; 


        public SampleAdapter(Context context, List<SampleData> sampleData) {
            this.context = context;
            this.sampleData = sampleData;
            this.arraylist = new ArrayList<SampleData>();
            this.arraylist.addAll(sampleData);
            imageLoader=new ImageLoader(ListActivity.this);
        }


        public class ViewHolder {
            TextView txtID,txtName,txtDescription;
            ImageView image;

        }

        public int getCount() {

            return sampleData.size();
        }

        public Object getItem(int position) {
            return sampleData.get(position);
        }

        public long getItemId(int position) {
            return sampleData.indexOf(getItem(position));
        }

        public View getView(final int position, View convertView, ViewGroup parent)
        {

            final ViewHolder holder;
            LayoutInflater mInflater = (LayoutInflater)
                    context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.custom_row, null);
                holder = new ViewHolder();
                holder.txtID = (TextView) convertView.findViewById(R.id.txt_id);
                holder.txtName = (TextView) convertView.findViewById(R.id.txt_name);
                holder.image = (ImageView) convertView.findViewById(R.id.image_view);
                convertView.setTag(holder);
            }
            else
            {
                holder = (ViewHolder) convertView.getTag();
            }


            holder.txtID.setText(sampleData.get(position).getId());
            holder.txtName.setText(sampleData.get(position).getName());

            imageLoader.DisplayImage(sampleData.get(position).getImage(), holder.image);

//          convertView.setOnClickListener(new OnClickListener() {
//              Intent intent=null;
//              @Override
//              public void onClick(View v) {
//                  Log.e("description....",sampleData.get(position).getDescription()+"");
//                  intent=new Intent(ListActivity.this, DetailActivity.class);
//                  intent.putExtra("description", sampleData.get(position).getDescription());
//                  startActivity(intent);
//                  finish();
//              }
//          });
            return convertView;
        }

        // Filter Class
        public void filter(String charText) {
            charText = charText.toLowerCase(Locale.getDefault());
            sampleData.clear();
            if (charText.length() == 0) {
                sampleData.addAll(arraylist);

            } else {
                for (SampleData st : arraylist) {
                    if (st.getName().toLowerCase(Locale.getDefault()).contains(charText)) {
                        sampleData.add(st);
                    }else if (st.getId().toLowerCase(Locale.getDefault()).contains(charText)) {
                        sampleData.add(st);
                    }
                    else if (st.getName().toLowerCase(Locale.getDefault()).contains(charText)) {
                        sampleData.add(st);
                    }
                }
            }
            notifyDataSetChanged();
        }

    }


    public String loadJSONFromAsset() {
        String json = null;
        try {

            InputStream is = getAssets().open("sample.json");

            int size = is.available();

            byte[] buffer = new byte[size];

            is.read(buffer);

            is.close();

            json = new String(buffer, "UTF-8");


        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        }
        return json;

    }


}

SampleData.java ( src folder )

public class SampleData 
{

    private String id;
    private String name;
    private String image;
    private String description;


    public SampleData(String id, String name, String image, String description) {
        super();
        this.id = id;
        this.name = name;
        this.image = image;
        this.description = description;
    }


    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getImage() {
        return image;
    }
    public void setImage(String image) {
        this.image = image;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }


}

add following permissions in AndroidManifest.xml file

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

thats it..

enjoy coding

Chare answered 15/5, 2014 at 7:1 Comment(0)
A
1

//Main Activity

Intent intent = new Intent(getApplicationContext(),
ListActivity.class);
intent.putExtra("name", name);
intent.putExtra("number", number);
startActivity(intent);

Then ListActivity.class

EditText search;
ListView lvDetail;
Contact data;
MyBaseAdapter adapter;
ArrayList<Contact> myList = new ArrayList<Contact>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list);
    lvDetail = (ListView) findViewById(R.id.lvCustomList);
    search = (EditText) findViewById(R.id.inputSearch);
    String[] name = getIntent().getStringArrayExtra("name");
    String[] number = getIntent().getStringArrayExtra("number");
    // System.out.println((1>2?1:(1==2?1:(2>3?2:3))));
    for (int i = 0; i < name.length; i++) {
        data = new Contact();
        data.setName(name[i]);
        data.setPhonenum(number[i]);
        data.setImgResId(img[i]);
        myList.add(data);
    }
    adapter = new MyBaseAdapter(getApplicationContext(), myList);
    lvDetail.setAdapter(adapter);
    lvDetail.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

        }
    });
    search.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int start, int before,
                int count) {
                   String text = search.getText().toString().toLowerCase(Locale.getDefault());
                   adapter.filter(text);


        }
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            // TODO Auto-generated method stub

        }

        @Override
        public void afterTextChanged(Editable s) {
            // TODO Auto-generated method stub

        }
    });
}

//Custom Adapter

 public class MyBaseAdapter extends BaseAdapter {
 ArrayList<Contact> myList = new ArrayList<Contact>();
 LayoutInflater inflater;
 Context context;
 private ArrayList<Contact> privatearray;
 public MyBaseAdapter(Context context,ArrayList<Contact> myList) {
     this.myList = myList;
     this.context = context;
     inflater = LayoutInflater.from(this.context);
     privatearray=new ArrayList<Contact>();
     privatearray.addAll(myList);
}


@Override
public int getCount() {
    // TODO Auto-generated method stub
    return myList.size();
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return myList.get(position);
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
}

@Override
public View getView(int position, View view, ViewGroup arg2) {
    //LayoutInflater inflater = getLayoutInflater();

    View row;
    row = inflater.inflate(R.layout.layout_list_item, arg2, false);
    TextView title, detail;
    ImageView i1;
    i1=(ImageView)row.findViewById(R.id.ivIcon);
    title = (TextView) row.findViewById(R.id.name);
    detail = (TextView) row.findViewById(R.id.phonenumber);
    i1=(ImageView)row.findViewById(R.id.ivIcon);
    //ListActivity activity=(ListActivity)Arrays.asList(myList)[0];
    //ListData data=myList.get(0);

   // Log.d("list", String.valueOf(myList.size())+" "+String.valueOf(data.getDescription()));
    i1.setImageResource(myList.get(position).getImgResId());
    title.setText(myList.get(position).getName());
    detail.setText(myList.get(position).getPhonenum());
    return (row);
}
// Filter Class
public void filter(String charText) {

    charText = charText.toLowerCase(Locale.getDefault());
    myList.clear();
    if(charText.length()==0){
        myList.addAll(privatearray);
    }
    else{
        for (Contact c : privatearray) {
            if (c.getName().toLowerCase(Locale.getDefault())
                    .contains(charText)) {
                myList.add(c);
            }
        }
    }
    notifyDataSetChanged();


}

}

//and Model

public class Contact {
String phonenum;
String name;
int imgResId;
public String getPhonenum() {
    return phonenum;
}
public void setPhonenum(String phonenum) {
    this.phonenum = phonenum;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public int getImgResId() {
    return imgResId;
}
public void setImgResId(int imgResId) {
    this.imgResId = imgResId;
}

}

Aboard answered 1/12, 2014 at 13:46 Comment(0)
S
0

You could give this a try:

    public class MyAdapter extends ArrayAdapter<Model> {

          public MyAdapter(Context context, int textViewResourceId,
                 List<model> objects) {
               super(context, textViewResourceId, objects);
          }

          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
               TextView tx = (TextView)convertView;
               SpannableString text = getItem(position);
               for(char:typedChar)
               if(tx.getText().contains(char)){

                    // make "text" (characters pos-1 to pos) red  

                    text.setSpan(new ForegroundColorSpan(Color.RED), 

tx.getText().indexOf(char) - 1, tx.getText().indexOf(char), 0);  

                    textView.setText(text, BufferType.SPANNABLE);
               }
          }
     }

Then Finally Register Editext here:

 edit.addTextChangedListener(new TextWatcher(){
        public void afterTextChanged(Editable s) {

           //Modify letter here by simple parsing
        }
        public void beforeTextChanged(CharSequence s, int start, int count, int after){}
        public void onTextChanged(CharSequence s, int start, int before, int count){}
    });

Hope this could help you ...

Spectra answered 31/1, 2014 at 8:59 Comment(0)
S
0

Update your own code only:

searchString = searchString.trim().toLowerCase();
for (int i = 0; i < arraylist.size(); i++)
{
    String currentString = arraylist.get(i).get(BAPTISMAL_SONG.TAG_TITLE).trim().toLowerCase();
    if (currentString.startsWith(searchString))
    {
        arrayTemplist.add(arraylist.get(i));
    }
}

The code below maybe help you.

private ArrayList<HashMap<String, String>> arrayDatalist = new ArrayList<HashMap<String,String>>();
...

@Override
protected void onCreate(Bundle savedInstanceState) {

    ....

    arrayDatalist.addAll(arraylist);
    adapter2 = new ListViewAdapterBaptismal(BAPTISMAL_SONG.this, arrayDatalist);
    listview.setAdapter(adapter2);

    searchInput.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){
            if (searchInput.isEnabled()){
                searchString = searchInput.getText().toString().trim().toLowerCase();
                if (searchLocationOperation!=null && searchLocationOperation.getStatus().equals(Status.RUNNING)){
                    searchLocationOperation.cancel(true);
                }
                searchLocationOperation = new SearchLocationOperation(searchString);
                searchLocationOperation.execute();
            }
        }
    });
}

private class SearchLocationOperation extends AsyncTask<Void, Void, String> {   
    private ArrayList<HashMap<String, String>> searchResult = new ArrayList<HashMap<String,String>>();
    private String searchString;

    public SearchLocationOperation(String str){
        searchString = str;
    }

    @Override
    protected String doInBackground(Void... params) {                       
        if (searchString.length() <= 2) {
            searchResult.addAll(arraylist);                
        }else{
            for (HashMap<String, String> rowItem: arraylist)
            {

                //if (rowItem.get(BAPTISMAL_SONG.TAG_TITLE).toLowerCase().contains(searchString))  //If get filter with any part of the name
                if (rowItem.get(BAPTISMAL_SONG.TAG_TITLE).toLowerCase().startWiths(searchString))
                {
                    searchResult.add(rowItem);
                }
                if (isCancelled()) return null;
            }
        }
        return null;
    }

    @Override
    protected void onPreExecute() {         
        //Show progress if needed
        super.onPreExecute();
    }       

    @Override
    protected void onPostExecute(String result) {           
        //Hide progress if showed

        if (!isCancelled() && arrayDatalist!=null && adapter2!=null){           
            arrayDatalist.clear();
            arrayDatalist.addAll(searchResult);
            adapter2.notifyDataSetChanged();
        }

        super.onPostExecute(result);
    }
}
Savitt answered 31/1, 2014 at 9:26 Comment(3)
Does not it work any more or it start work when input length >=2, It is, please change "if (searchString.length() <= 2) {" to "if (searchString.length() <= 0) {". If it do not work, can you describe how it is?Savitt
Actually I just want to use the code above, I'm nearly there but there's something wrong with the logicVerbosity
As the updated, You need compare the title with the search string (do not compare the search string with the title). And you should switch between "startWiths" and "contains" method depend on your logic.Savitt
C
0
arrayTemplist.clear();

for (int i = 0; i < mainArray.size(); i++) {
    if (searchString.length()<= mainArray.get(i).length()) {
        if (editText
            .getText()
            .toString()
            .equalsIgnoreCase(
                (String) mainArray.get(i).subSequence(0,
                    searchString.length()))) {
                        arrayTemplist.add(mainArray.get(i));
                    }
        }
}
adapter = new ListViewAdapterBaptismal(BAPTISMAL_SONG.this, arrayTemplist);
listview.setAdapter(adapter);
adapter.notifyDataSetChanged();

use this `onTextChanged() method, might be it will help you.

Clavier answered 31/1, 2014 at 10:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.