Bộ lọc Chế độ xem Danh sách Android


94

Tôi đã tạo chế độ xem danh sách trong android và tôi muốn thêm văn bản chỉnh sửa phía trên danh sách và khi người dùng nhập văn bản, danh sách sẽ được lọc theo đầu vào của người dùng

bất cứ ai có thể cho tôi biết xin vui lòng nếu có một cách để lọc danh sách bộ điều hợp trong Android?


1
Hi thử ví dụ này Ví dụ một và thứ hai Ví dụ 2 tôi đã thực hiện với cùng dựa trên tutorials..I này hy vọng điều này sẽ giúp bạn
Pragnani

5
Câu trả lời hàng đầu chỉ không cung cấp đủ thông tin cho tôi. Câu trả lời cho một câu hỏi tương tự này có nhiều ngữ cảnh hơn và chính xác là đủ thông tin để giúp tôi sắp xếp.
James Skemp

Tôi đang sử dụng chế độ xem tái chế Tôi muốn lọc các bản ghi nhưng tôi đang sử dụng các nút tùy chỉnh để cung cấp đầu vào cho văn bản chỉnh sửa như bàn phím tùy chỉnh nhưng tôi nhận được sự chậm trễ khi nhấp nhanh vào nút, bạn có thể giúp tôi thoát khỏi điều này không. Tôi có hàng nghìn bản ghi
Sagar

Câu trả lời:


141

Thêm một EditText ở đầu listview của bạn trong tệp bố cục .xml của nó. Và trong hoạt động / phân đoạn của bạn ..

lv = (ListView) findViewById(R.id.list_view);
    inputSearch = (EditText) findViewById(R.id.inputSearch);

// Adding items to listview
adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.product_name,    products);
lv.setAdapter(adapter);       
inputSearch.addTextChangedListener(new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
        // When user changed the Text
        MainActivity.this.adapter.getFilter().filter(cs);
    }

    @Override
    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { }

    @Override
    public void afterTextChanged(Editable arg0) {}
});

Điều cơ bản ở đây là thêm OnTextChangeListener vào văn bản chỉnh sửa của bạn và bên trong phương thức gọi lại của nó, áp dụng bộ lọc cho bộ điều hợp listview của bạn.

BIÊN TẬP

Để có được bộ lọc để BaseAdapter tùy chỉnh của bạn, bạn "sẽ cần phải thực hiện lọc giao diện.

class CustomAdapter extends BaseAdapter implements Filterable {

    public View getView(){
    ...
    }
    public Integer getCount()
    {
    ...
    }

    @Override
    public Filter getFilter() {

        Filter filter = new Filter() {

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {

                arrayListNames = (List<String>) results.values;
                notifyDataSetChanged();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

                FilterResults results = new FilterResults();
                ArrayList<String> FilteredArrayNames = new ArrayList<String>();

                // perform your search here using the searchConstraint String.

                constraint = constraint.toString().toLowerCase();
                for (int i = 0; i < mDatabaseOfNames.size(); i++) {
                    String dataNames = mDatabaseOfNames.get(i);
                    if (dataNames.toLowerCase().startsWith(constraint.toString()))  {
                        FilteredArrayNames.add(dataNames);
                    }
                }

                results.count = FilteredArrayNames.size();
                results.values = FilteredArrayNames;
                Log.e("VALUES", results.values.toString());

                return results;
            }
        };

        return filter;
    }
}

Bên trong PerformFiltering (), bạn cần so sánh thực tế của truy vấn tìm kiếm với các giá trị trong cơ sở dữ liệu của mình. Nó sẽ chuyển kết quả của nó đến phương thức publishResults () .


Tôi đã tạo một bộ điều hợp tùy chỉnh mở rộng BaseAdapter và bên trong nó, tôi đã xác định một Vectơ của đối tượng của tôi sẽ được hiển thị trong danh sách, khi tôi cố gắng sử dụng mã trên, tôi không thể tìm thấy phương thức getFilter trong Bộ điều hợp của mình, bạn cũng vậy xin vui lòng cho tôi biết nếu tôi phải thực hiện bất kỳ giao diện ??
Amira Elsayed Ismail

Lọc dữ liệu trong trường hợp BaseAdapter hơi phức tạp. Bạn sẽ phải triển khai giao diện Filterable để triển khai BaseAdapter. Sau đó, bạn sẽ có phương thức getFilter () và bên trong nó, bạn phải triển khai hai phương thức gọi lại để làm việc; void xuất bảnResults () và FilterResults performanceFiltering (ràng buộc CharSequence).
Purush Pawar

bạn có thể hỗ trợ với một ví dụ đơn giản xin vui lòng?
Amira Elsayed Ismail

Đúng. Kiểm tra phần EDIT của câu trả lời của tôi.
Purush Pawar

1
Tôi đề nghị bạn đăng một câu hỏi khác trên SO về điều này. Bởi vì nó không phải là một cách thích hợp để tiếp tục đặt những câu hỏi khác nhau vào cùng một bài đăng. Vâng, lưu ý, chỉ cần sao chép toàn bộ danh sách mảng vào một danh sách mảng tạm thời khác trước tiên và bên trong phương thức onPerformFiltering () sử dụng danh sách tạm thời này để tìm kiếm. Điều này sẽ giải quyết vấn đề của bạn. Và hãy ủng hộ và / hoặc chấp nhận câu trả lời nếu nó giúp ích cho bạn.
Purush Pawar

9

Triển khai bộ điều hợp của bạn Có thể lọc:

public class vJournalAdapter extends ArrayAdapter<JournalModel> implements Filterable{
private ArrayList<JournalModel> items;
private Context mContext;
....

sau đó tạo lớp Bộ lọc của bạn:

private class JournalFilter extends Filter{

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults result = new FilterResults();
        List<JournalModel> allJournals = getAllJournals();
        if(constraint == null || constraint.length() == 0){

            result.values = allJournals;
            result.count = allJournals.size();
        }else{
            ArrayList<JournalModel> filteredList = new ArrayList<JournalModel>();
            for(JournalModel j: allJournals){
                if(j.source.title.contains(constraint))
                    filteredList.add(j);
            }
            result.values = filteredList;
            result.count = filteredList.size();
        }

        return result;
    }
    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        if (results.count == 0) {
            notifyDataSetInvalidated();
        } else {
            items = (ArrayList<JournalModel>) results.values;
            notifyDataSetChanged();
        }
    }

}

theo cách này, bộ điều hợp của bạn có thể lọc, bạn có thể chuyển mục bộ lọc vào bộ lọc của bộ điều hợp và thực hiện công việc. Tôi hy vọng điều này sẽ có ích.


1

Trong trường hợp bất kỳ ai vẫn quan tâm đến chủ đề này, tôi thấy rằng cách tiếp cận tốt nhất để lọc danh sách là tạo một lớp Lọc chung và sử dụng nó với một số kỹ thuật phản ánh / chung cơ sở có trong gói Java old school SDK. Đây là những gì tôi đã làm:

public class GenericListFilter<T> extends Filter {

    /**
     * Copycat constructor
     * @param list  the original list to be used
     */
    public GenericListFilter (List<T> list, String reflectMethodName, ArrayAdapter<T> adapter) {
        super ();

        mInternalList = new ArrayList<>(list);
        mAdapterUsed  = adapter;

        try {
            ParameterizedType stringListType = (ParameterizedType)
                    getClass().getField("mInternalList").getGenericType();
            mCompairMethod =
                    stringListType.getActualTypeArguments()[0].getClass().getMethod(reflectMethodName);
        }
        catch (Exception ex) {
            Log.w("GenericListFilter", ex.getMessage(), ex);

            try {
                if (mInternalList.size() > 0) {
                    T type = mInternalList.get(0);
                    mCompairMethod = type.getClass().getMethod(reflectMethodName);
                }
            }
            catch (Exception e) {
                Log.e("GenericListFilter", e.getMessage(), e);
            }

        }
    }

    /**
     * Let's filter the data with the given constraint
     * @param constraint
     * @return
     */
    @Override protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results = new FilterResults();
        List<T> filteredContents = new ArrayList<>();

        if ( constraint.length() > 0 ) {
            try {
                for (T obj : mInternalList) {
                    String result = (String) mCompairMethod.invoke(obj);
                    if (result.toLowerCase().startsWith(constraint.toString().toLowerCase())) {
                        filteredContents.add(obj);
                    }
                }
            }
            catch (Exception ex) {
                Log.e("GenericListFilter", ex.getMessage(), ex);
            }
        }
        else {
            filteredContents.addAll(mInternalList);
        }

        results.values = filteredContents;
        results.count  = filteredContents.size();
        return results;
    }

    /**
     * Publish the filtering adapter list
     * @param constraint
     * @param results
     */
    @Override protected void publishResults(CharSequence constraint, FilterResults results) {
        mAdapterUsed.clear();
        mAdapterUsed.addAll((List<T>) results.values);

        if ( results.count == 0 ) {
            mAdapterUsed.notifyDataSetInvalidated();
        }
        else {
            mAdapterUsed.notifyDataSetChanged();
        }
    }

    // class properties
    private ArrayAdapter<T> mAdapterUsed;
    private List<T> mInternalList;
    private Method  mCompairMethod;
}

Và sau đó, điều duy nhất bạn cần làm là tạo bộ lọc dưới dạng lớp thành viên (có thể trong "onCreate" của Chế độ xem) chuyển tham chiếu bộ điều hợp, danh sách của bạn và phương thức được gọi để lọc:

this.mFilter = new GenericFilter<MyObjectBean> (list, "getName", adapter);

Điều duy nhất còn thiếu bây giờ, là ghi đè phương thức "getFilter" trong lớp bộ điều hợp:

@Override public Filter getFilter () {
     return MyViewClass.this.mFilter;
}

Tất cả đã được làm xong! Bạn sẽ lọc thành công danh sách của mình - Tất nhiên, bạn cũng nên triển khai thuật toán lọc theo cách tốt nhất mô tả nhu cầu của bạn, đoạn mã dưới đây chỉ là một ví dụ. . Hy vọng nó sẽ giúp, hãy cẩn thận.


Tôi không biết về android, nhưng tôi nhớ đã được yêu cầu cố gắng tránh phản chiếu nếu có thể trong c # vì nó khá tốn tài nguyên (tôi thường làm việc trên các ứng dụng di động windows nên đây có thể là vấn đề), điều này có áp dụng trên android không? hay sự phản chiếu có tác dụng tương tự như việc xây dựng một lớp thực tế mà không có generic? Tôi đang nghĩ đến việc tạo một mẫu để có thể lọc và chỉ thêm lớp và phương thức được sử dụng làm tham số
Cruces

Vâng, bạn chính xác. Điều tương tự cũng áp dụng ở đây, sự phản chiếu mang lại sức nặng cho quá trình xử lý chương trình, nhưng trong trường hợp này, việc sử dụng nó rất đơn giản và bởi vì chúng ta đang sử dụng nó với ký hiệu chung / mẫu, nó cũng giúp ích cho trình biên dịch. Chúc may mắn!
jbrios777

NB Bạn có thể gặp vấn đề với làm mờ (dexguard / proguard) nếu bạn sử dụng phản xạ.
Alexey
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.