Android Searchview with list view and LoaderCallBack

Im trying to implement a contact listview with a pageloader to manage loading on demand and a searchview to search within the list, but I cant get it working. I am all contacts in app.allContacts. The problem is that the searchview is not working. and I dont know if its the loaderCallback or the searchview.

public class ContactsFragment extends SherlockListFragment {

private SeparatedListAdapter sl;
private SumaApplication app;
private ContactAdapter allContacts;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    app = (SumaApplication) getActivity().getApplication();
    allContacts = new ContactAdapter(getActivity());
    sl = new SeparatedListAdapter(new HeaderAdaptor(getActivity(), R.layout.section_title, new ArrayList<String>()));
    sl.addSection(getResources().getString(R.string.all_contacts), allContacts);
    setListAdapter(sl);
    getLoaderManager().initLoader(0, null, loaderCallbak);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_list_contacts, container, false);
    ((SearchView) v.findViewById(R.id.contacts_to)).setOnQueryTextListener(queryListener);
    searchView = new SearchViewImpl(getActivity());
    searchView.setOnQueryTextListener(queryListener);
    searchView.setOnCloseListener(closeListener);
    searchView.setIconifiedByDefault(true);
    return v;
}

@Override
public void onDestroyView() {
    super.onDestroyView();
}

private SearchView searchView;

private OnCloseListener closeListener = new OnCloseListener() {

    @Override
    public boolean onClose() {
        searchView.setQuery(null, true);
        return true;
    }
};

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);

     Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" +((Contact) l.getItemAtPosition(position)).getInfo())); 
     startActivity(callIntent);
}

private LoaderCallbacks<List<Contact>> loaderCallbak = new LoaderCallbacks<List<Contact>>() {

    @Override
    public Loader<List<Contact>> onCreateLoader(int arg0, Bundle arg1) {
        ContactPageLoader cpl = new ContactPageLoader(getActivity(), app);
        cpl.setFilter(currentFilter);
        return cpl;
    }

    @Override
    public void onLoadFinished(Loader<List<Contact>> arg0, List<Contact> contacts) {
       app.getAllContacts().subList(0, Math.min(app.getAllContacts().size() - 1, 3)));

        allContacts.update(app.getAllContacts());

        ((SeparatedListAdapter) getListAdapter()).notifyDataSetInvalidated();
        ((SeparatedListAdapter) getListAdapter()).notifyDataSetChanged();
    }

    @Override
    public void onLoaderReset(Loader<List<Contact>> arg0) {
    }
};

private static class ContactAdapter extends ArrayAdapter<Contact> {
    private LayoutInflater inflater;

    public ContactAdapter(Context context) {
        super(context, -1);
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    public void update(List<Contact> contacts) {
        if (contacts == null) {
            return;
        }

        setNotifyOnChange(false);

        clear();
        addAll(contacts);

        notifyDataSetChanged();

    }

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

        if (convertView == null) {
            convertView = inflate(getContext());
        }

        fill((ViewGroup) convertView, getItem(position));

        return convertView;

    }

    private View inflate(Context context) {

        View convertView = inflater.inflate(R.layout.contact_row, null, false);

        convertView.setTag(R.id.contact_avatar, convertView.findViewById(R.id.contact_avatar));
        convertView.setTag(R.id.contact_name, convertView.findViewById(R.id.contact_name));
        convertView.setTag(R.id.contact_info, convertView.findViewById(R.id.contact_info));

        return convertView;
    }

    private static void fill(ViewGroup rl, Contact contact) {
        fillTextView(rl, R.id.contact_name, contact.getName());
        fillTextView(rl, R.id.contact_info, contact.getInfo());
    }



    private static void fillTextView(ViewGroup rl, int id, String description) {
        TextView t = ((TextView) rl.getTag(id));
        t.setText(description);
    }

}

public static class ContactPageLoader extends AsyncTaskLoader<List<Contact>> {

    private SumaApplication app;
    private String filter = null;

    public ContactPageLoader(Context context, SumaApplication app) {
        super(context);
        this.app = app;
    }

    public void setFilter(String filter) {
        this.filter = filter;
    }

    @Override
    public List<Contact> loadInBackground() {
            List<Contact> temp = new ArrayList<Contact>();
            for(Contact c : app.getAllContacts()){
                if(c.getName().matches("(.*)"+filter+"(.*)")){
                    temp.add(c);
                }
            }
            return temp;
    }

    @Override
    protected void onStartLoading() {
        super.onStartLoading();
        forceLoad();
    }
}

private String currentFilter = null;

private OnQueryTextListener queryListener = new OnQueryTextListener() {

    @Override
    public boolean onQueryTextSubmit(String query) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        // Called when the action bar search text has changed. Update
        // the search filter, and restart the loader to do a new query
        // with this filter.

        String newFilter = newText;

        // Don't do anything if the filter hasn't actually changed.
        // Prevents restarting the loader when restoring state.
        if (currentFilter == null && newFilter == null) {
            return true;
        }
        if (currentFilter != null && currentFilter.equals(newFilter)) {
            return true;
        }
        currentFilter = newFilter;
        getLoaderManager().restartLoader(0, null, loaderCallbak);
        return true;
    }
};

private static class SearchViewImpl extends SearchView {
    public SearchViewImpl(Context context) {
        super(context);
    }

    // The normal SearchView doesn't clear its search text when
    // collapsed, so we will do this for it.
    @Override
    public void onActionViewCollapsed() {
        setQuery("", false);
        super.onActionViewCollapsed();
    }
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawingCacheQuality="high"
android:orientation="vertical" >

<SearchView
    android:id="@+id/contacts_to"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#f1f1f1"
    android:iconifiedByDefault="false"
    android:paddingBottom="20dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="20dp"
    android:queryHint="@string/query_hint"
    android:visibility="visible"
    android:/>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f7f7f7"
    android:orientation="vertical"
    android:padding="20dp"
    android:visibility="visible" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@color/separator_line"
        android:dividerHeight="1dp" >
    </ListView>
</LinearLayout>

Answers


Change the onCreateView like this.. Your using SearchView in your layout xml(not SearchViewImpl)

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_list_contacts, container, false);
    searchView =  (SearchView) v.findViewById(R.id.contacts_to);
    searchView.setOnQueryTextListener(queryListener);
    searchView.setOnCloseListener(closeListener);
    searchView.setIconifiedByDefault(true);
    return v;
}

private LoaderCallbacks<List<Contact>> loaderCallbak = new LoaderCallbacks<List<Contact>>() {

    @Override
    public Loader<List<Contact>> onCreateLoader(int arg0, Bundle arg1) {
        ContactPageLoader cpl = new ContactPageLoader(getActivity(), app);
        cpl.setFilter(currentFilter);
        return cpl;
    }

    @Override
    public void onLoadFinished(Loader<List<Contact>> arg0, List<Contact> contacts) {

        if(currentFilter == null){
            allContacts.update(app.getAllContacts());
        } else{
            allContacts.update(temp);
        }

        ((SeparatedListAdapter) getListAdapter()).notifyDataSetInvalidated();
        ((SeparatedListAdapter) getListAdapter()).notifyDataSetChanged();

    }

Need Your Help

Creating a Click Event for A Dynamically Created Button On A Dynamically Created Tab

c# winforms button tabs click

I am having trouble creating a click event for a dynamically created button on a dynamically created Tab. I keep having an exception thrown. The program creates a Tab for each directory within a

Eclipse CDT not generating symbols for new projects

c++ eclipse symbols eclipse-cdt

All new projects I create in eclipse lack any automatic includes (such as the standard library) or any of the default Paths and Symbols that are usually generated automatically. The only way I can ...