使用自定义适配器过滤ListView

时间:2015-01-01 11:25:46

标签: android search android-listview filter

我有一个listview,可以加载设备上所有已安装的应用程序。我想过滤listview的结果,以便用户可以通过键入其名称而不是滚动列表视图来查找应用程序。但我不知道如何实现这个,因为我使用的是自定义适配器。感谢您提前提出任何建议。

ListView Activity使用异步任务加载所有应用

    class loadList extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        loadinglayout.setVisibility(View.VISIBLE);
        lockbutton.setEnabled(false);
    }

    @Override
    protected String doInBackground(String... params) {
        // TODO Auto-generated method stub
        parent = getActivity().getBaseContext();
        final PackageManager packageManager = parent.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN, null);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        List<ResolveInfo> resInfos = packageManager.queryIntentActivities(
                intent, 0);

        HashSet<String> packageNames = new HashSet<String>(0);
        appInfos = new ArrayList<ApplicationInfo>(0);

        for (ResolveInfo resolveInfo : resInfos) {
            if ((resolveInfo.activityInfo.packageName.toString())
                    .equals("com.mypackage")) {
                continue;
            } else {
                packageNames.add(resolveInfo.activityInfo.packageName);
            }
        }

        for (String packageName : packageNames) {
            try {
                appInfos.add(packageManager.getApplicationInfo(packageName,
                        PackageManager.GET_META_DATA));
            } catch (NameNotFoundException e) {
                // Do Nothing
            }
        }
        Collections.sort(appInfos,
                new ApplicationInfo.DisplayNameComparator(packageManager));
        return null;
    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);

        adapter = new ApkAdapter(getActivity().getApplicationContext(),
                R.layout.apklist_item, appInfos);
        loadinglayout.setVisibility(View.GONE);
        lView.setAdapter(adapter);
        lockbutton.setEnabled(true);

    }

}

我的适配器

   public class ApkAdapter extends ArrayAdapter<ApplicationInfo> {
private List<ApplicationInfo> appsList = null;
private Context context;
private PackageManager packageManager;
DataBaseHandler handler;
String[] LockedApps;
Typeface fontFamily = Typeface.createFromAsset(getContext().getAssets(),
        "fontawesome-webfont.ttf");

public ApkAdapter(Context context, int textViewResourceId,
        List<ApplicationInfo> appsList) {
    super(context, textViewResourceId, appsList);
    this.context = context;
    this.appsList = appsList;

    packageManager = context.getPackageManager();
    handler = new DataBaseHandler(getContext());
    try {
        handler.open();
        LockedApps = handler.getPackages();
        handler.close();
    } catch (Exception E) {
        LockedApps = null;
        System.out.println("in constructor exception");
    }
}

@Override
public int getCount() {
    return ((null != appsList) ? appsList.size() : 0);
}

@Override
public ApplicationInfo getItem(int position) {
    return ((null != appsList) ? appsList.get(position) : null);
}

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

public boolean isEnabled(int position) {
    return false;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view = convertView;
    if (null == view) {
        LayoutInflater layoutInflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = layoutInflater.inflate(R.layout.apklist_item, null);
    }

    final ApplicationInfo data = appsList.get(position);
    if (position % 2 == 0) {
        view.setBackgroundColor(Color.parseColor("#fafafa"));
    } else {
        view.setBackgroundColor(Color.parseColor("#eeeeee"));
    }
    if (null != data) {

        final TextView appName = (TextView) view
                .findViewById(R.id.app_name);
        TextView packageName = (TextView) view
                .findViewById(R.id.app_package);
        final TextView lockstatus = (TextView) view
                .findViewById(R.id.lock_status);
        ImageView iconview = (ImageView) view.findViewById(R.id.app_icon);
        appName.setTypeface(fontFamily);
        appName.setTextColor(Color.BLACK);
        appName.setText(data.loadLabel(packageManager));
        packageName.setText(data.packageName);
        lockstatus.setTypeface(fontFamily);
        try {
            if (Arrays.asList(LockedApps).contains(
                    data.packageName.toString())) {
                lockstatus.setText("\uf205");

            } else if (LockedApps == null) {
                lockstatus.setText("\uf204");

            } else {
                lockstatus.setText("\uf204");
            }
        } catch (Exception E) {
            lockstatus.setText("\uf204");
        }

        lockstatus.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) { // TODO Auto-generated method stub

                if (lockstatus.getText().toString().equals("\uf204")) {
                    handler.open();
                    handler.insertPackage(data.packageName.toString());
                    LockedApps = handler.getPackages();
                    handler.close();
                    Toast.makeText(
                            getContext(),
                            appName.getText().toString()
                                    + " has been locked",
                            Toast.LENGTH_SHORT).show();
                    lockstatus.setText("\uf205");
                } else if (lockstatus.getText().toString().equals("\uf205")) {
                    handler.open();
                    handler.deletePackage("'" + data.packageName.toString()
                            + "'");
                    LockedApps = handler.getPackages();
                    handler.close();
                    Toast.makeText(
                            getContext(),
                            appName.getText().toString()
                                    + " has been unlocked",
                            Toast.LENGTH_SHORT).show();
                    lockstatus.setText("\uf204");
                }
            }
        });

        iconview.setImageDrawable(data.loadIcon(packageManager));
    }
    return view;
}
};

4 个答案:

答案 0 :(得分:0)

这可以实现。你必须根据你的搜索键盘过滤掉数据并调用相同的片段或活动。它将重建视图。

答案 1 :(得分:0)

ArrayAdapter已经支持过滤。但是,它内置逻辑会在toString()对象上调用ApplicationInfo并在其上执行startsWith(String search_criteria)。如果这适合你,那么你所要做的就是打电话:

adapter.getFilter().filter(search_string);

过滤器将处理更新适配器和ListView。通常,您将实现一个SearchView,它将处理用户输入的String并调用适配器上的getFilter()。但是,这不是一项要求

如果ArrayAdapter过滤逻辑对您不起作用,那么您可以实现BaseAdapter而不是ArrayAdapter类,并从头开始编写自己的过滤器和适配器。或者您可以使用third party library,它允许您轻松实现逻辑,而无需从头开始编写整个适配器。

附注,您无需在nullgetCount方法中进行getItem检查。如果您看到null出现,则表示您做错了。

答案 2 :(得分:0)

你需要创建一个扩展filter.try的类,我已经将它用于我的一个项目。我认为它与你的代码相匹配。在适配器文件中的View GetView()下添加appfilter类。

  private class AppFilter extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        // TODO Auto-generated method stub
        constraint = constraint.toString().toLowerCase();
        FilterResults result = new FilterResults();
        if (constraint != null && constraint.toString().length() > 0) {
            List<ApplicationInfo> filteredItems = new ArrayList<ApplicationInfo>();
            for (int i = 0, l = appsList.size(); i < l; i++) {
                ApplicationInfo data = appsList.get(i);
                String name = data.loadLabel(packageManager).toString();
                if (name.toLowerCase().contains(constraint)) {
                    filteredItems.add(data);
                }
            }
            result.count = filteredItems.size();
            result.values = filteredItems;
        } else {
            synchronized (this) {
                result.values = appsList;
                result.count = appsList.size();
            }
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint,
            FilterResults results) {
        // TODO Auto-generated method stub
        appsList = (ArrayList<ApplicationInfo>) results.values;
        notifyDataSetChanged();
        clear();
        for (int i = 0; i < appsList.size(); i++)
            add(appsList.get(i));
        notifyDataSetInvalidated();
    }

}

您还需要初始化并覆盖过滤器类的构造函数

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

并在主列表文件中

        searchtext.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {
            // TODO Auto-generated method stub
            adapter.getFilter().filter(s.toString());
        }

        @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

        }
    });

答案 3 :(得分:0)

我遇到过这个图书馆。 https://github.com/bhavyahmehta/ListviewFilter 我认为它会解决你的目的。