Android ListView does not refresh by Filter
Asked Answered
R

4

14

In my application I have three fragment with ViewPager. one of this fragments i have simple Arraylist as ListView from phones contact list and i'm trying to filter that after typing into edittext. but doesn't refresh until softkeyboard is visible and I must have to hide keyboard to refresh list view by filtered strings.

For example:

filter listview by "a":

adapter.getFilter().filter("a");

My adapter:

public class AdapterContacts extends BaseAdapter implements Filterable {

    private LayoutInflater inflater;
    private Context context;
    private List<ContactLists> categoryArrayList;
    private final ArrayList<ContactLists> originalList = new ArrayList<ContactLists>();
    private NameFilter filter;

    public AdapterContacts(ArrayList<ContactLists> array) {
        categoryArrayList = array;
    }

    public AdapterContacts(Context context, List<ContactLists> array) {
        this.context = context;
        inflater = LayoutInflater.from(this.context);
        categoryArrayList = array;
        originalList.addAll(array);
    }

    @Override
    public int getCount() {
        return categoryArrayList.size();
    }

    @Override
    public ContactLists getItem(int position) {
        return categoryArrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder mViewHolder;

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.layout_contacts_list_item, null);
            mViewHolder = new ViewHolder(convertView);
            convertView.setTag(mViewHolder);
        } else {
            mViewHolder = (ViewHolder) convertView.getTag();
        }

        ContactLists item = getItem(position);
        mViewHolder.fillItems(this, item, position);

        return convertView;
    }

    private static class UI extends HelperUI {
        public TextView tv_person_nickname_mobile_number;
        public TextView btn_invite_message;
        public ImageView img_contact_image;
        public ImageView imgv_user_rank;
        public TextView tv_contact_name;
        public LinearLayout ll_root;

        public UI(View view) {
            parseUi(view);
        }
    }

    private class ViewHolder {
        private UI UI;

        public ViewHolder(View view) {
            UI = new UI(view);
        }

        public void fillItems(final AdapterContacts adapter, final ContactLists item, final int position) {
            UI.tv_contact_name.setText(item.getContact_name());

            if (item.getStatus() == 1) {
                UI.btn_invite_message.setVisibility(View.GONE);
                UI.imgv_user_rank.setVisibility(View.VISIBLE);

                if (item.getRank() != null || !TextUtils.isEmpty(item.getRank())) {
                    //Picasso.with(G.context).load(item.getRank()).into(UI.imgv_user_rank);
                }

                UI.tv_person_nickname_mobile_number.setText(item.getNick_name());
                //UI.ll_root.setBackgroundDrawable(G.context.getResources().getDrawable(R.drawable.selector_button_actions));
                if (item.getContact_image() == null || TextUtils.isEmpty(item.getContact_image())) {
                    Bitmap bitmap = UC.getContactPhoto(item.getMobile_number(), G.context.getContentResolver());
                    if (bitmap != null) {
                        UI.img_contact_image.setImageBitmap(bitmap);
                    } else {
                        UI.img_contact_image.setImageDrawable(G.context.getResources().getDrawable(R.drawable.no_avatar));
                    }
                } else {
                    // show user avatar from web
                    //Picasso.with(G.context).load(item.getContact_image()).into(UI.img_contact_image);
                    UI.img_contact_image.setImageBitmap(BitmapFactory.decodeFile(G.dir_image + "/" + item.getContact_image()));
                }
            } else {
                // UI.ll_root.setBackgroundDrawable(G.context.getResources().getDrawable(R.drawable.selector_invite_actions));
                UI.btn_invite_message.setVisibility(View.VISIBLE);
                UI.imgv_user_rank.setVisibility(View.GONE);
                UI.btn_invite_message.setText(UC.getString(R.string.invite_person));
                UI.btn_invite_message.setBackgroundDrawable(G.context.getResources().getDrawable(R.drawable.shape_invite_button_default));
                UI.tv_person_nickname_mobile_number.setText(item.getMobile_number());
                Bitmap bitmap = UC.getContactPhoto(item.getMobile_number(), G.context.getContentResolver());
                if (bitmap != null) {
                    UI.img_contact_image.setImageBitmap(bitmap);
                } else {
                    UI.img_contact_image.setImageDrawable(G.context.getResources().getDrawable(R.drawable.no_avatar));
                }
            }
        }
    }

    @Override
    public Filter getFilter() {
        if (filter == null) {
            filter = new NameFilter();
        }
        return filter;
    }

    public class NameFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            String searchText = constraint.toString().toLowerCase();
            ArrayList<ContactLists> newList = filterListBasedOnSearchText(searchText);
            results.values = newList;
            results.count = newList.size();

            return results;
        }

        private ArrayList<ContactLists> filterListBasedOnSearchText(String constraint) {
            ArrayList<ContactLists> newList = new ArrayList<ContactLists>();

            int l = originalList.size();
            for (int i = 0; i < l; i++) {
                ContactLists nameList = originalList.get(i);

                if (nameList.getContact_name().toString().contains(constraint)) {
                    newList.add(nameList);
                }
            }

            return newList;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint,
                FilterResults results) {
            categoryArrayList = (ArrayList<ContactLists>) results.values;
            notifyDataSetChanged();
        }
    }
}

softkeyboard status status in Manifest for ActivityMain. this class have view pager with three fragment:

    <activity android:name=".Activities.ActivityBootstrap" android:windowSoftInputMode="adjustPan"  android:screenOrientation="portrait"/>

other way to do Filter in fragment without Adapter's ability

edt_sample.addTextChangedListener(new TextWatcher() {
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

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

    @Override
    public void afterTextChanged(Editable s) {
        String text = edt_sample.getText().toString();
        filter(text);
    }
});

public void filter(String charText) {
    drinks.clear();
    if (charText.length() == 0) {
        drinks.addAll(contact_list);
    } else {
        for (ContactLists wp : contact_list) {
            if (wp.getContact_name().contains(charText)) {
                drinks.add(wp);
            }
        }
    }
    contact_list.clear();
    contact_list.addAll(drinks);
    adapter.notifyDataSetChanged();
}

ListView succesful filtered by when i close or hide softkeyboard that refresh with nw items.

Raper answered 28/6, 2015 at 5:26 Comment(11)
why don't you use ContactsContract.CommonDataKinds.Phone.html#CONTENT_FILTER_URI ?Kev
@Kev how to use that sir? can you help me?Raper
see codeshare.io/2JXuvKev
@Kev i dont test it sir. please wait to reply thanksRaper
"please wait to reply thanks" what do you mean?Kev
@Kev testing code and put result information of test in here :) english is not my native language sir. i'm sorryRaper
i dont understand you at all...Kev
So the afterTextChanged method isn't called until the soft keyboard is hidden, right?Lacquer
@Lacquer yes. problem is only listview refresh after close softkeyboardRaper
Please follow tutorialsbuzz.com/2014/08/…, to make your baseadapter filterable. Hope this may help you.Nacelle
@Nacelle i dont have any problem on filter listview sir.Raper
G
2

You're not making use of your adapter filter as I see from the code posted by you. I'll post here an example filter and how to call it (kept all your variable names to make it easier).

The 'NameFilter' class, inside your adapter class:

public class NameFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results = new FilterResults();

        String searchText = constraint.toString().toLowerCase();
        ArrayList<ContactLists> newList = filterListBasedOnSearchText(searchText);
        results.values = newList;
        results.count = newList.size();

        return results;
    }

    private ArrayList<ContactLists> filterListBasedOnSearchText(String constraint) {
        ArrayList<ContactLists> newList = new ArrayList<ContactLists>();

        int l = originalList.size();
        for (int i = 0; i < l; i++) {
            ContactLists nameList = originalList.get(i);

            if (nameList.getContact_name().toString().contains(constraint)) {
                newList.add(nameList);
            }
        }

        return newList;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint,
            FilterResults results) {
        categoryArrayList = (ArrayList<ContactLists>) results.values;
        notifyDataSetChanged();
    }
}

The 'TextWatcher' interface method implementation in your list fragment:

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

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

public void afterTextChanged(Editable s) {
    String text = searchView.getText().toString();
    NameFilter itemFilter = (NameFilter) adapter.getFilter();
    itemFilter.filter(text);
}

Also, some observations:

  • if 'ContactLists' is a contact, name it 'Contact', to avoid confusion
  • I would use a 'SearchView', instead of an 'EditText'
  • I don't know how you get the contact list, but there's a guide about it here (if you didn't look at it already)
Gibbie answered 2/7, 2015 at 10:16 Comment(13)
thanks sir, but listview doesnt refresh until softkeyboard is visibleRaper
to make sure I understood: the list doesn't filter while you type (and the keyboard is visible)? have you used the implementation above? Also, make sure that you use the 'categoryArrayList' in the adapter 'getView' method.Gibbie
yes doesnt work until keyboard visible. after type listview dont filter, when i close softkeyboard by press back on phone listview refresh by filtered type in edit textRaper
hmm - strange - maybe you could try calling 'invalidateViews()' on the listview after filtering, to force a redraw/rebuild of the view - what os are you testing on? and if doing tests on a device, what device are you using?Gibbie
i'm testing app on real device on android os version 4.2Raper
tested on a 4.2 emulator with the support view pager and I can filter as I type (I don't have a device with 4.2 - could you tell me please what device you're using?). Also, if you can, please add the code for the 'getView' method and 'UI' and 'ViewHolder' classesGibbie
and you're using the NameFilter in 'afterTextChanged', right? also, what device model are you using? I can't reproduce your issue :(Gibbie
is 'afterTextChanged' method called every time you edit the 'EditText'?Gibbie
can you send your sample code like with my code sir?Raper
unfortunately i dont access to chat. i dont know why :(Raper
I just added the 'src' and 'layout' folders. filedropper.com/edittext and filedropper.com/searchview Also, if you want to test them by creating a project, you should add the support-v4 jar and a reference to the appcompat-v7 libraryGibbie
your implementation is in afterTextChanged, your implementation should be in onTextChanged. onTextChanged is invoked everytime you hit a key on the keyboard.Dockyard
both methods are called as you type (or if you modify the text somehow). Look here for more details: #477348Gibbie
L
0

It is very simple to implement. Please follow these below steps:

Step 1: Initialize Edittext:

     editTextVideoFolderSearch = (EditText) rootView.findViewById(R.id.editTextVideoFolderSearch);

Step 2: Add TextChangedListener on this edittext. like:

editTextVideoFolderSearch.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence t, int start, int before,
                int count) {
            videoDetailBeansSearch.clear();
                for (int i = 0; i < videoDetailBeans_total.size(); i++) {
                    if (videoDetailBeans_total.get(i).getAlbum().toLowerCase()
                            .contains(t)) {
                        videoDetailBeansSearch.add(videoDetailBeans_total.get(i));
                    }
                }
                if (videoDetailBeansSearch.size() > 0) {
                    video_folder_gridView.setAdapter(new AlbumGridAdapter(getActivity(), videoDetailBeansSearch));
                } else {
                    video_folder_gridView.setAdapter(new AlbumGridAdapter(getActivity(), videoDetailBeansSearch));
                }
        }

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

        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    });

Step 3: you have to make different beans for populating the adapter in list view:

    private ArrayList<MediaDetailBean> videoDetailBeansSearch = new ArrayList<MediaDetailBean>();
    private ArrayList<MediaDetailBean> videoDetailBeans_total = new ArrayList<MediaDetailBean>();
    private ArrayList<MediaDetailBean> videoDetailBeans_delete = new ArrayList<MediaDetailBean>();

Step 4: Polulate the list at the time of Activity or fragment loaded:

public class GetVideoAsynctask extends AsyncTask<String, String,Object[]> {

        ProgressDialog progressDialog ;
        String response = "";
        int offset, limit;

        public GetVideoAsynctask(int offset1, int limit1) {
          offset = offset1;
          limit = limit1;
        }

        @Override
        public void onPreExecute() {
            progressDialog = ProgressDialog.show(getActivity(),"Loading...", "Please Wait");
        }

        @Override
        public Object[] doInBackground(String... params) {

            return AppParsing.getMediaDetails(getActivity(), AppPreferenceUtils.getChildUploadDeviceId(getActivity()),
                                AppPreferenceUtils.getChildRaId(getActivity()),"2", offset, limit,"3"); 
        //// type=1 for image,2 for video,3 for audio
        }  

        @SuppressWarnings("unchecked")
        @Override
        public void onPostExecute(Object[] result) {
            progressDialog.cancel();
            try
            {
                boolean status = (Boolean) result[0];
                response = (String) result[1];

                if(status)
                {
                    videoDetailBeans = (ArrayList<MediaDetailBean>) result[2] ; 

                    for (int i = 0; i < videoDetailBeans.size(); i++) {
                        videoDetailBeans_total.add(videoDetailBeans.get(i));
                    }

                    isCheck_video = new boolean[videoDetailBeans_total.size()];

                    for(int i=0;i<videoDetailBeans_total.size();i++)
                    {
                        if(!GRID_DATA.contains(videoDetailBeans_total.get(i).getAlbum()))
                        {
                            GRID_DATA.add(videoDetailBeans_total.get(i).getAlbum());
                        }
                    }

                    video_folder_gridView.setAdapter(new AlbumGridAdapter(getActivity(), videoDetailBeans_total));

                    //Toast.makeText(getActivity(), response, Toast.LENGTH_SHORT).show();
                }
                else
                {
                    response = (String) result[1];
                    AppUtils.showDialog(getActivity(), response);
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

Step 5: Set the listview adapter like:

new GetVideoAsynctask(offset1, limit1).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

Step 6: Most important thinning is i am taking load more list view here:

com.costum.android.widget.LoadMoreListView) video_folder_gridView = (com.costum.android.widget.LoadMoreListView)     rootView.findViewById(R.id.video_folder_gridView);

Step 7: In my xml i am declaring like this:

   <com.costum.android.widget.LoadMoreListView
    android:id="@+id/video_folder_gridView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnWidth="90dp"
    android:gravity="center"
    android:horizontalSpacing="10dp"
    android:numColumns="auto_fit"
    android:stretchMode="columnWidth"
    android:verticalSpacing="10dp" />

Feel free if you have any query regarding this concept.

Lucrative answered 7/7, 2015 at 9:6 Comment(0)
R
0

This is my implementation of Filter which filters while you type a single letter.This is the Activity implementation...

 public class MessagesActivity extends Activity{

       private ListView msgListView;
       private EditText mSearchContent;
       private MessagesAdapter msgAdapter;
       public static ArrayList<MessagesBean> allMsgsList = new ArrayList<MessagesBean>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_messages);
            init();
            msgAdapter = new MessagesAdapter(getApplicationContext(), allMsgsList, MessagesActivity.this);
            msgListView.setAdapter(msgAdapter);
    }
    private void init() {
            // TODO Auto-generated method stub
            msgListView = (ListView) findViewById(R.id.messages_list);
            msgListView.setOnScrollListener(this);


            mSearchContent.addTextChangedListener(new TextWatcher() {
                public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
                }

                public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
                }

                public void afterTextChanged(Editable s) {

                    msgAdapter.getFilter().filter(s.toString());
                }
            });


}

This is the Adapter implementation

public class MessagesAdapter extends BaseAdapter implements Filterable {

    private Context mcontext;
    private ArrayList<MessagesBean> all_details, dup_all_details;
    private LayoutInflater inflater;
    private DisplayImageOptions options;
    private CustomClickLisntener clickLisntener;

    private MessagesBean mMessagesBean;
    private ViewHolder selectedHolder;
    private ListViewFilter listviewFilter;

    // int pos = 0;
    public MessagesAdapter(Context context, ArrayList<MessagesBean> all_list, CustomClickLisntener lisntener) {
        mcontext = context;
        all_details = all_list;

        clickLisntener = lisntener;
        inflater = (LayoutInflater) mcontext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        options = new DisplayImageOptions.Builder().cacheInMemory(true).cacheOnDisk(true).build();
        dup_all_details = all_list;
    }

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

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

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

    static class ViewHolder {
        TextView user_name, msg_sub, msg_content, msg_time;
        ImageView user_image;

    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder viewholder = null;
        if (convertView == null) {
            viewholder = new ViewHolder();
            convertView = inflater.inflate(R.layout.row_item_inbox_msg, null);

            viewholder.user_name = (TextView) convertView.findViewById(R.id.user_name);
            viewholder.msg_time = (TextView) convertView.findViewById(R.id.msg_time);
            viewholder.msg_sub = (TextView) convertView.findViewById(R.id.msg_subject);
            viewholder.user_image = (ImageView) convertView.findViewById(R.id.user_image);
            viewholder.msg_content = (TextView) convertView.findViewById(R.id.msg_content);

            // viewholder.down_arrow.setTag(position);
            convertView.setTag(viewholder);

        } else {
            viewholder = (ViewHolder) convertView.getTag();
        }

        mMessagesBean = all_details.get(position);
        viewholder.user_name.setText(mMessagesBean.getFirstname().trim() + " " + mMessagesBean.getLastname());
        viewholder.msg_time.setText(DateDifferent.getDateDifferance(mMessagesBean.getSentDate()));
        viewholder.msg_sub.setText(mMessagesBean.getSubject());
        viewholder.msg_content.setText(mMessagesBean.getMessage());

        ImageLoader.getInstance().displayImage(mMessagesBean.getUserimage(), viewholder.user_image, options);

        return convertView;
    }

    @Override
    public Filter getFilter() {
        // TODO Auto-generated method stub
        if (listviewFilter == null) {
            listviewFilter = new ListViewFilter();

        }
        return listviewFilter;
    }

    public class ListViewFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            // TODO Auto-generated method stub
            constraint = constraint.toString();

            ArrayList<MessagesBean> allitems = new ArrayList<MessagesBean>();

            FilterResults filterresults = new FilterResults();

            if (constraint != null && constraint.toString().length() > 0) {

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

                    if (dup_all_details.get(i).getFirstname().contains(constraint)
                            || dup_all_details.get(i).getLastname().contains(constraint)) {
                        allitems.add(dup_all_details.get(i));

                    }

                }

                filterresults.count = allitems.size();
                filterresults.values = allitems;

            } else {

                System.out.println(" iam here..." + all_details.size());

                synchronized (this) {
                    filterresults.count = allitems.size();
                    filterresults.values = allitems;
                }

            }

            return filterresults;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            // TODO Auto-generated method stub

            all_details = (ArrayList<MessagesBean>) results.values;
            MessagesActivity.allMsgsList = all_details;
            MessagesAdapter.this.notifyDataSetChanged();

        }

    }

}
Ratio answered 16/7, 2015 at 4:2 Comment(0)
M
0

You can do it like:

public void filter(String charText) {
    drinks.clear();
    if (charText.length() == 0) {
        drinks.addAll(contact_list);
    } else {
        for (ContactLists wp : contact_list) {
            if (wp.getContact_name().contains(charText)) {
                drinks.add(wp);
            }
        }
    }
    contact_list.clear();
    contact_list.addAll(drinks);
    adapter.notifyDataSetChanged(contact_list);
}

and in your adapter:

public void notifyDataSetChanged(List<ContactLists> items){
   this.categoryArrayList = items;
   super.notifyDataSetChanged();
}
Mccormack answered 16/7, 2015 at 11:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.