【问题标题】:Filter listview with spinner then searchbox (edittext)使用微调器然后搜索框过滤列表视图(edittext)
【发布时间】:2017-10-16 03:11:17
【问题描述】:

我有一个包含汽车的列表视图,例如汽车名称、汽车的一些详细信息。我想找到一辆车的名字。

  1. 我使用 Android 微调器按汽车的当前状态(运行、停止、...)过滤汽车

  2. 然后,我在 Spinner 旁边的搜索框中(使用 editetext)输入汽车名称。它应该在 Spinner 中过滤具有状态选择的汽车。

我知道如何将它们分开但不在一起。如何将微调器过滤器和搜索过滤器结合在一起?非常感谢您的帮助!

CarlistFragment1CarListFragment2

Car(Model) 在创建列表视图时,我像往常一样拥有 setter 和 getter 方法。

汽车适配器代码:

//This car list adapter class provides data to list view
public class CarListAdapter extends BaseAdapter implements Filterable{

    private Context context;
    private LayoutInflater inflater;
    private List<Car> carList; // Original Data
    private List<Car> carListSpinnerFiltered; // spinner filtered data
    //private List<Car> carListSearchFiltered;  // search filtered data
    private ValueFilter valueFilter;
    private ImageLoader imageLoader = AppController.getInstance().getImageLoader();

    public CarListAdapter(Context context, List<Car> carList) {
        this.context = context;
        this.carList = carList;
        this.carListSpinnerFiltered = carList;
        //this.carListSearchFiltered  = carList;
    }

    @Override
    public int getCount() {
        return carList.size();
    }

    @Override
    public Object getItem(int position) {
        return carList.get(position);
    }

    @Override
    public long getItemId(int position) {
//        return position;
        return carList.indexOf(getItem(position));
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (inflater == null)
            inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null)
            convertView = inflater.inflate(R.layout.list_row_carlist, null);

        if (imageLoader == null)
            imageLoader = AppController.getInstance().getImageLoader();
        NetworkImageView thumbNail = (NetworkImageView) convertView
                .findViewById(R.id.car_image);

        TextView devname  = (TextView) convertView.findViewById(R.id.devname);
        TextView location = (TextView) convertView.findViewById(R.id.location);
        TextView status   = (TextView) convertView.findViewById(R.id.status);
        TextView speed    = (TextView) convertView.findViewById(R.id.speed);

        // getting vehicle data for the row
        final Car c = carList.get(position);

        // thumbnail image
//        thumbNail.setImageUrl(c.getImageURL(), imageLoader);

        // device name
        devname.setText(c.getDevname());

        // location
        if (c.getLocation().equals("")) {
            location.setText(String.valueOf("Location unknown"));
        } else {
            location.setText(String.valueOf(c.getLocation()));
        }

        // status
            switch (c.getStatus()) {
                case "run":
                    status.setText(String.valueOf(statusRun));
                    status.setTextColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorCarRun));
                    break;

                case "stop":
                    status.setText(String.valueOf(statusStop));
                    status.setTextColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorCarStop));
                    break;

                case "lost_gprs":
                    status.setText(String.valueOf(statusLostGprs));
                    status.setTextColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorBlack));
                    break;

                case "lost_gps":
                    status.setText(String.valueOf(statusLostGps));
                    status.setTextColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorffbf00));
                    break;

                case "expired":
                    status.setText(String.valueOf("Expired"));
                    status.setTextColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorBlue));
                    break;
            }

        // speed
        speed.setText(String.valueOf(c.getSpeed()));

        return convertView;
    }

    @Override
    public Filter getFilter() {
        if (valueFilter == null) {
            valueFilter = new ValueFilter();
        }
        return valueFilter;
    }

    private class ValueFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();


            // Search Field
//            if (constraint != null && constraint.length() > 0 ) {
//                ArrayList<Car> filterList = new ArrayList<>();
//
//                for (int i = 0; i < carListSearchFiltered.size(); i++) {
//
//                    String devname = carListSearchFiltered.get(i).getDevname().toUpperCase();
//                    String inputString = constraint.toString().toUpperCase();
//
//                    if (devname.contains(inputString)) {
//                        Car car = new Car();
//                        car.setDevname(carListSearchFiltered.get(i).getDevname());
//                        car.setLocation(carListSearchFiltered.get(i).getLocation());
//                        car.setStatus(carListSearchFiltered.get(i).getStatus());
//                        car.setSpeed(carListSearchFiltered.get(i).getSpeed());
//                        car.setDevid(carListSearchFiltered.get(i).getDevid());
//                        filterList.add(car);
//                    }
//
//
//                } // end for loop
//
//                results.count = filterList.size();
//                results.values = filterList;
//
//            } else {
//                results.count = carListSearchFiltered.size();
//                results.values = carListSearchFiltered;
//            }



            // Spinner Filter
            String inputStatus = constraint.toString();

            if (!inputStatus.equals("All")) {

                ArrayList<Car> spinnerList = new ArrayList<>();

                for (int i = 0; i < carListSpinnerFiltered.size(); i++){
                    String carStatus = carListSpinnerFiltered.get(i).getStatus();

                    switch (carStatus){
                        case "run":
                            carStatus = "run";
                            break;

                        case "stop":
                            carStatus = "stop";
                            break;

                        case "lost_gprs":
                            carStatus = "lost_gprs";
                            break;

                        case "lost_gps":
                            carStatus = "lost_gps";
                            break;

                        default:
                            Toast.makeText(context, "status unknown", Toast.LENGTH_SHORT).show();
                            break;

                    } // end switch

                    if (carStatus.equals(inputStatus)) {

                        Car car = new Car();
                        car.setDevname(carListSpinnerFiltered.get(i).getDevname());
                        car.setLocation(carListSpinnerFiltered.get(i).getLocation());
                        car.setStatus(carListSpinnerFiltered.get(i).getStatus());
                        car.setSpeed(carListSpinnerFiltered.get(i).getSpeed());
                        car.setDevid(carListSpinnerFiltered.get(i).getDevid());
                        spinnerList.add(car);

                    }

                } // end for loop

                results.count = spinnerList.size();
                results.values = spinnerList;

            } else {

                results.count = carListSpinnerFiltered.size();
                results.values = carListSpinnerFiltered;
            }

            return results;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            carList = (List<Car>) results.values;
            notifyDataSetChanged();
        }

    } // end class

}

【问题讨论】:

    标签: android listview filter spinner


    【解决方案1】:

    我注意到的第一个问题是,您正在使用过滤结果覆盖存储在 carList 中的原始汽车列表。这意味着当过滤器被清除时,您将无法恢复它们。

    如果您为原始数据集保留一个列表,并为您将要显示的数据保留另一个列表,您可能会发现会更容易。最初这些将是相同的。然后在performFilter 中,您可以从完整列表中重新创建包含您想要的汽车的显示列表。

    对于您的实际问题,Filter 类似乎无法处理多种约束类型。如果您打算使用它,则每次调用 performFilter 时,您都需要您的过滤器来执行两种类型的过滤。你可以在你的适配器上创建你自己的方法,接收来自你的微调器的状态过滤器和来自你的搜索框的文本过滤器,并用一个特殊字符加入它们,比如|。示例:

    lost_gps|mysearch

    然后在performFilter() 方法中将它们分开。

    另一点是,如果状态未知,您在performFilter 中的 switch 语句实际上只是显示一个 Toast。任何分配都不做任何事情,它可以被 if 语句替换,您可以在其中测试每个状态,或者如果状态在预制的 HashSet 对象中更好,然后您可以只使用 Set.contains()

    更新:

    为了进一步充实这个想法,在你的适配器中你会有类似的东西

    class Adapter ... {
        private String mStatusFilter = "";
        private String mSearchFilter = "";
    
        private void setStatusFilter(String statusFilter) {
            mStatusFilter = statusFilter;
            getFilter().filter(mStatusFilter + "|" + mSearchFilter);
        }
    
        private void setSearchFilter(String searchFilter) {
            mSearchFilter = searchFilter;
            getFilter().filter(mStatusFilter + "|" + mSearchFilter);
        }
    }
    

    然后在您的过滤器类中

    performFiltering(CharSequence constraint) {
       displayedCarList.clear();
       String statusFilter = constraint.split("|")[0]
       String searchFilter = constraint.split("|")[1]
       for(Car car: carList) {
           // Does it match the status? (if filter not set, default to yes)
           boolean statusMatch = TextUtils.isEmpty(statusFilter) ||
                car.status.equals(statusFilter);
           // Does it match the name? (if filter not set, default to yes)
           boolean searchMatch = TextUtils.isEmpty(searchFilter) ||
                car.name.contains(searchFilter);
           if(statusMatch && searchMatch) {
               displayedCarList.add(car)
           }
       }
       ...
    }
    

    适配器只会显示displayedCarList 中的所有汽车。

    【讨论】:

    • 感谢您的评论,但我仍然不太了解。我不能同时实现两个过滤器。微调器将显示所有具有当前选定状态的汽车。只有这样,用户才想在微调结果中过滤特定的汽车。问题是 performFilter() 只接受一个约束。如何分别过滤具有多个约束的列表视图?这很难。我解决不了这个人!
    • 我在代码中充实了我的想法,这有帮助吗?能不能详细解释一下你不明白的部分?
    • 我还在尝试
    • 您的代码是为了表明 performFiltering() 同时接受 2 个约束,对吗?我需要的是在第一个约束之后(如我的代码中的汽车状态)列表视图过滤一次。然后我添加另一个约束,它与第一个约束一起过滤一次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多