1

As of right now I have three tabs (scrollable ) which are fragments with an ActionBarActivity implements ActionBar.TabListener

enter image description here

I am attempting to add the searchview function when I press the search icon so an edittext pops up to filter which apps I want to search for.

I am aiming for something like this: enter image description here

Currently I am trying to implement what I learned from this:

List Filter Custom Adapter dont give result

Android - Actionbar Sherlock - Search Filter

Android ActionBar Customize Search View

So right now I have this in my ActionBarActivity:

@Override
    public boolean onCreateOptionsMenu(Menu menu){
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.block, menu);

        final EditText editText = (EditText) menu.findItem(
                R.id.action_search).getActionView();
        editText.addTextChangedListener(textWatcher);

        MenuItem menuItem = menu.findItem(R.id.action_search);
        menuItem.setOnActionExpandListener(new OnActionExpandListener() {
            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {
                // Do something when collapsed
                return true; // Return true to collapse action view
            }

            @Override
            public boolean onMenuItemActionExpand(MenuItem item) {
                editText.clearFocus();
                return true; // Return true to expand action view
            }
        });

        return super.onCreateOptionsMenu(menu);
    }
    private TextWatcher textWatcher = new TextWatcher() {

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

            if (null != mAdapter) {
                mAdapter.getFilter().filter(s);
            }
        }

The problem is that the getFilter method cannot be resolved. I am not sure to do in this case.

My adapter class is:

package com.ibc.android.demo.appslist.app;

import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.TextView;
import android.view.View.OnClickListener;

import com.spicycurryman.getdisciplined10.app.R;

import java.util.List;

public class ApkAdapter extends BaseAdapter {


    List<PackageInfo> packageList;
    Activity context;
    PackageManager packageManager;
    boolean[] itemChecked;

    public ApkAdapter(Activity context, List<PackageInfo> packageList,
                      PackageManager packageManager) {
        super();
        this.context = context;
        this.packageList = packageList;
        this.packageManager = packageManager;
        itemChecked = new boolean[packageList.size()];
    }

    private class ViewHolder {
        TextView apkName;
        CheckBox ck1;
    }

    public int getCount() {
        return packageList.size();
    }

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

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

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

        LayoutInflater inflater = context.getLayoutInflater();

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.installed_apps, null);
            holder = new ViewHolder();

            holder.apkName = (TextView) convertView
                    .findViewById(R.id.appname);
            holder.ck1 = (CheckBox) convertView
                    .findViewById(R.id.checkBox1);

            convertView.setTag(holder);
             //holder.ck1.setTag(packageList.get(position));

        } else {

            holder = (ViewHolder) convertView.getTag();
        }
        // ViewHolder holder = (ViewHolder) convertView.getTag();
        PackageInfo packageInfo = (PackageInfo) getItem(position);

        Drawable appIcon = packageManager
                .getApplicationIcon(packageInfo.applicationInfo);
        String appName = packageManager.getApplicationLabel(
                packageInfo.applicationInfo).toString();
        appIcon.setBounds(0, 0, 75, 75);
        holder.apkName.setCompoundDrawables(appIcon, null, null, null);
        holder.apkName.setCompoundDrawablePadding(15);
        holder.apkName.setText(appName);
        holder.ck1.setChecked(false);

        if (itemChecked[position])
            holder.ck1.setChecked(true);
        else
            holder.ck1.setChecked(false);

        holder.ck1.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                if (holder.ck1.isChecked())
                    itemChecked[position] = true;
                else
                    itemChecked[position] = false;
            }
        });

        return convertView;

    }



}

What would I need to change in my adapter class to resolve the getFilter method error and why? I also would like to know if there is a more optimal/efficient way to implement the search in the action bar ...?

Community
  • 1
  • 1
Rohit Tigga
  • 2,373
  • 9
  • 43
  • 81

2 Answers2

3

first implements Filterable in ApkAdapter class

add this in apkAdapter clas

    @Override
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new ItemsFilter();
        }
        return mFilter;
    }

    private class ItemsFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            // TODO Auto-generated method stub

            ArrayList<PackageInfo> packageList_2 = packageList;
            String prefixString = prefix.toString().toLowerCase();
            FilterResults results = new FilterResults();
            ArrayList<PackageInfo> FilteredList = new ArrayList<PackageInfo>();

            if (prefix == null || prefix.length() == 0) {
                results.values = packageList_2;
                results.count = packageList_2.size();
                return results;
            }
            for (int i = 0; i < packageList_2.size(); i++) {
                String filterText = prefix.toString().toLowerCase();
                try {
                    PackageInfo data = packageList_2.get(i);
                    if (data.applicationInfo
                            .loadLabel(getActivity().getPackageManager())
                            .toString().toLowerCase().contains(filterText)) {
                        FilteredList.add(data);
                    } else if (data.packageName.contains(filterText)) {
                        FilteredList.add(data);
                    }
                } catch (Exception e) {
                    Toast.makeText(getActivity(),
                            "exception e" + e.toString(),
                            Toast.LENGTH_SHORT).show();
                }
            }
            results.values = FilteredList;
            results.count = FilteredList.size();
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint,
                FilterResults results) {
            Toast.makeText(getActivity(),"result-0 "+results.count,
                     Toast.LENGTH_SHORT).show(); 
            packageList = (List<PackageInfo>) results.values;
            notifyDataSetChanged();

        }
    }

then add this in OnCreateOptionMenu

    @Override
      public boolean onCreateOptionsMenu(Menu menu){
     MenuInflater inflater = getMenuInflater();
     inflater.inflate(R.menu.block, menu);

        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            if (!isLoading()) {
                mAppAdapter.getFilter().filter(query);
            }
            return true;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            if (!isLoading()) {
                if (newText.equals("")) {
                    mAppAdapter.getFilter().filter("");
                }
            }
            return true;
        }
    });
Sumit
  • 1,022
  • 13
  • 19
1

ApkAdapter has to implement the Filterable interface. Then you'll need to actually write your own Filtering logic to perform the filter. Keep in mind, all the filtering logic happens on a background thread. That means all your adapter mutate methods will need to have sync locks...unless you know with absolute certainty, your adapter will never change once loaded.

Note, your implementation of ApkAdapter is not doing anything that the ArrayAdapter can't do. So extending the ArrayAdapter class would probably be better as it already supports filtering. However, I should point out that there are filtering bugs with the ArrayAdapter.

Alternatively, if you want to avoid all the hassle of writing your own filtering code, I suggest checking out this alternative.

Ifrit
  • 6,791
  • 8
  • 50
  • 79