使用自定义适配器过滤 ListView

Filter ListView with custom adapter

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

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;
}
};

这可能是 implemented.you 必须根据您的搜索键盘过滤掉数据并调用相同的片段,否则 activity.It 将重建视图。

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

adapter.getFilter().filter(search_string);

过滤器将相应地处理更新您的适配器和 ListView。通常你会实现一个 SearchView 来处理用户输入的字符串并调用你的适配器上的 getFilter() 。但是,这不是必需的

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

旁注,无需在 getCountgetItem 方法中执行 null 检查。如果您看到 null 出现,则表示您做错了。

你需要创建一个 class 来扩展 filter.try 我已经将它用于我的一个项目..tweeked 它以匹配你的代码。在您的适配器文件中的 View GetView() 下添加 appfilter class。

  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();
    }

}

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

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

        }
    });

我偶然发现了这个图书馆。 https://github.com/bhavyahmehta/ListviewFilter 我想它会解决你的目的。