使用ArrayAdapter进行ListView筛选



我正试图让我的列表视图使用搜索框来过滤列表视图中已安装的应用程序。我尝试过各种方法,比如重写toString()方法和重写getFilter()方法,但似乎都不起作用。

主要活动:

public class AllApplicationsActivity extends Activity {
    private ListView mListAppInfo;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // set layout for the main screen
        setContentView(R.layout.layout_main);
        // load list application
        mListAppInfo = (ListView)findViewById(R.id.lvApps);
        EditText search = (EditText)findViewById(R.id.EditText01);
        mListAppInfo.setTextFilterEnabled(true);
        // create new adapter
        final AppInfoAdapter adapter = new AppInfoAdapter(this, Utilities.getInstalledApplication(this), getPackageManager());

        // set adapter to list view  
        mListAppInfo.setAdapter(adapter);

        search.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) {
                Log.e("TAG", "ontextchanged");
               adapter.getFilter().filter(s); //Filter from my adapter
               adapter.notifyDataSetChanged(); //Update my view
            }
        });
        // implement event when an item on list view is selected
        mListAppInfo.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView parent, View view, int pos, long id) {
                // get the list adapter
                AppInfoAdapter appInfoAdapter = (AppInfoAdapter)parent.getAdapter();
                // get selected item on the list
                ApplicationInfo appInfo = (ApplicationInfo)appInfoAdapter.getItem(pos);
                // launch the selected application
                //Utilities.launchApp(parent.getContext(), getPackageManager(), appInfo.packageName);
                Utilities.getPermissions(parent.getContext(), getPackageManager(), appInfo.packageName);
                //Toast.makeText(MainActivity.this, "You have clicked on package: " + appInfo.packageName, Toast.LENGTH_SHORT).show();
            }
        });

    }
}

AppInfoAdapter

public class AppInfoAdapter extends ArrayAdapter<ApplicationInfo> {
    private Context mContext;
    PackageManager mPackManager;
    public AppInfoAdapter(Context c, List<ApplicationInfo> list, PackageManager pm) {
        super(c, 0, list);
        mContext = c;
        mPackManager = pm;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // get the selected entry
        ApplicationInfo entry = (ApplicationInfo) getItem(position);
        Log.e("TAG", entry.toString());
        // reference to convertView
        View v = convertView;
        // inflate new layout if null
        if(v == null) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            v = inflater.inflate(R.layout.layout_appinfo, null);
        }
        // load controls from layout resources
        ImageView ivAppIcon = (ImageView)v.findViewById(R.id.ivIcon);
        TextView tvAppName = (TextView)v.findViewById(R.id.tvName);
        TextView tvPkgName = (TextView)v.findViewById(R.id.tvPack);
        // set data to display
        ivAppIcon.setImageDrawable(entry.loadIcon(mPackManager));
        tvAppName.setText(entry.loadLabel(mPackManager));
        tvPkgName.setText(entry.packageName);
        // return view
        return v;
    }
}

附加

public static List<ApplicationInfo> getInstalledApplication(Context context) {
    PackageManager packageManager = context.getPackageManager();
    List<ApplicationInfo> apps = packageManager.getInstalledApplications(0);
    Collections.sort(apps, new ApplicationInfo.DisplayNameComparator(packageManager));
    return apps;
}

使用TextWatcher应该可以。您可以尝试不调用setTextFilterEnabled,因为这将导致列表设置自己的过滤器,当列表具有焦点时,该过滤器将工作。

我的猜测是ApplicationInfo.toString()返回的不是您在列表中显示的内容。由于默认的ArrayAdapter筛选器在每个项上都与getString()匹配,因此您可能会针对一些意外的内容进行筛选。

您可以通过使用包装器对象并重写toString()来解决这个问题,或者构建自己的过滤器。

  @Override
  public Filter getFilter() {
    return mFilter;
  }
  private final Filter mFilter = new Filter() {
    @Override
    protected FilterResults performFiltering(CharSequence charSequence) {
      FilterResults results = new FilterResults();
      if (charSequence == null) {
        return results;
      }
      // snip
      results.values = /* snip */
      results.count = /* snip */
      return results;
    }
    @Override
    protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
      if (filterResults != null) {
        notifyDataSetChanged();
      } else {
        notifyDataSetInvalidated();
      }
    }
  };

至少,提供自己的过滤器可能有助于调试。此外,我可以想象提供一个过滤器,对包名称和标签进行正则表达式搜索。

最新更新