执行/向自定义ListView添加搜索功能

时间:2020-10-14 11:48:15

标签: java android android-listview android-package-managers

我为所有已安装的应用程序创建了一个自定义listView,但是我不知道如何添加搜索功能,因为它有点复杂(..my应用程序),有人可以帮助我吗? (picture of the app )

App.java-应用程序构造函数

public class App {
    private int number;
    private String name;
    private String version;
    private Drawable drawable;

    public App(int number, String name, String version, Drawable drawable){
        this.number = number;
        this.name = name;
        this.version = version;
        this.drawable = drawable;
    }
    //Getters & Setters...
}

AppAdapter.java-listView适配器

public class AppAdapter extends ArrayAdapter<App> {
    Context context;
    List<App> objects;

    public AppAdapter(Context context, int resources, int textViewResources, List<App> objects){
        super(context, resources, textViewResources, objects);

        this.context = context;
        this.objects = objects;
    }

    public View getView(int position, View convertView, ViewGroup parent){
        LayoutInflater layoutInflater = ((Activity)context).getLayoutInflater();
        View view = layoutInflater.inflate(R.layout.custom_card,parent,false);

        TextView tvName =  (TextView)view.findViewById(R.id.tvName);
        TextView tvVersion =  (TextView)view.findViewById(R.id.tvVersion);
        TextView tvNumber =  (TextView)view.findViewById(R.id.tvNumber);
        ImageView ivImage = (ImageView)view.findViewById(R.id.ivImage);

        App current = objects.get(position);
        tvName.setText(String.valueOf(current.getName()));
        tvVersion.setText(String.valueOf(current.getVersion()));
        tvNumber.setText(String.valueOf(current.getNumber()));
        ivImage.setImageDrawable(current.getDrawable());

        return view;
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {   
    ArrayList<App> appList;
    ListView lv;
    AppAdapter appAdapter;
    App lastSelected;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EditText etSearch = findViewById(R.id.etSearch);
        
        PackageManager packageManager = getPackageManager();
        List<PackageInfo> mApps = packageManager.getInstalledPackages(0);
        //array strings to all packages, names and version
        final String[] arrPackages = new String[mApps.size()];
        final String[] arrVersion = new String[mApps.size()];
        String[] arrName = new String[mApps.size()];
        //array of Drawables for icons...
        Drawable[] arrIcons = new Drawable[mApps.size()];
        App[] arrApps = new App[mApps.size()];
        appList = new ArrayList<>();
        //reading all app's packages and version to the arrays
        for (int i = 0; i < mApps.size(); i++){
            arrVersion[i] = mApps.get(i).versionName;
            arrPackages[i] = mApps.get(i).packageName;
        }

        for (int i = 0; i < mApps.size(); i++){
            try {//getting app's names from theres packages
                arrName[i] = (String) packageManager.getApplicationLabel(packageManager.getApplicationInfo(arrPackages[i], PackageManager.GET_META_DATA));
            } catch (PackageManager.NameNotFoundException e) {
                arrName[i] = "Unknown";
            }

            try {//same as names for icons
                arrIcons[i] = packageManager.getApplicationIcon(arrPackages[i]);
            } catch (PackageManager.NameNotFoundException e) {
                arrIcons[i] = getDrawable(R.drawable.placeholder);
            }
            arrApps[i] = new App(i + 1, "Name: "+arrName[i], "Version: "+arrVersion[i], arrIcons[i]);
            appList.add(arrApps[i]);
        }
        //on item click open app
        appAdapter = new AppAdapter(this,0,0,appList);
        lv = findViewById(R.id.lv);
        lv.setAdapter(appAdapter);

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                lastSelected = appAdapter.getItem(position);
                Intent launchIntent = getPackageManager().getLaunchIntentForPackage(arrPackages[position]);
                if (launchIntent != null) {
                    startActivity(launchIntent);//null pointer check in case package name was not found
                }
            }
        });

        //(trying to..) Add Text Change Listener to EditText
        etSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // Call back the Adapter with current character to Filter
                MainActivity.this.appAdapter.getFilter().filter(s.toString());
            }
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,int after) {
            }
            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    }
}

(当我尝试搜索某些内容时,什么都没有...)

1 个答案:

答案 0 :(得分:0)

交换此行

App current = objects.get(position);

对此

App current = (App) getItem(position);

您不需要将List<App> objects;保留在适配器中,它会在构造函数super调用(最后一个参数)中传递,并为您保留。检出ArrayAdapter source-传递的ArrayList保留为mObjects,并在某些方法中进一步使用,例如getPositiongetCountgetItem

ArrayAdapter已经implements Filterable,因此有一个覆盖的方法getFilter,它返回ArrayFilter-此内部类在底部声明。当您调用getFilter().filter(时,performFiltering被调用(在单独的线程中)并遍历数据的本地副本(第588行)。它使用values.get(i).toString().toLowerCase()比较来自数组的对象和传递的String(实际上是CharSequence)。因此在您的自定义App类中重写toString方法并在其中返回一些可搜索的值,例如

@Override
public String toString(){
    return name;
}

这不是最好的方法,因为toString可以用于许多机制(其Object的基本方法)中,并且在以上toString实现中,有两个App具有相同名称,但不同的versionnumber被同一对象威胁的事实,这是不正确的……也许更好的方法是return name+version+number;,但您仍然拥有{{ 1}}。这就是为什么我建议(在编辑之前在此答案中)使自己的类扩展Drawable并实现自己的过滤,或者至少使用BaseAdapter,但重写ArrayAdapter方法并返回自己的{ {1}}实现比较变量而不是使用getFilter。然后就不需要重写此类,保持原样。默认情况下,它返回种类的内存地址,因此对于每个新的Filter实例来说,它都是唯一的,即使使用完全相同的变量创建它也是如此

还在THIS答案中,您可以找到一个很好的示例,如何实现toString

相关问题