【问题标题】:Filter ListView with custom adapter使用自定义适配器过滤 ListView
【发布时间】:2015-01-01 11:25:45
【问题描述】:

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

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

【问题讨论】:

标签: android search android-listview filter


【解决方案1】:

您需要创建一个扩展过滤器的类。试试这个,我曾将它用于我的一个项目.. tweeked 以匹配您的代码。在适配器文件的 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

        }
    });

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      adapter.getFilter().filter(search_string);
      

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

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-08-12
          • 1970-01-01
          • 2020-12-06
          • 2018-11-29
          • 1970-01-01
          • 2014-09-06
          • 1970-01-01
          相关资源
          最近更新 更多