목록보기 필터 Android


94

나는 안드로이드에서 목록보기를 만들었고 목록 위에 편집 텍스트를 추가하고 싶습니다. 사용자가 텍스트를 입력하면 목록이 사용자 입력에 따라 필터링됩니다.

안드로이드에서 목록 어댑터를 필터링하는 방법이 있다면 누구든지 제발 말해 줄 수 있습니까?



5
상위 답변이 충분한 정보를 제공하지 않았습니다. 이 답변 유사한 질문에 대한 더 많은 컨텍스트를 가지고, 나를 정리 얻을 수있는 충분한 정보가 정확했다.
James Skemp

나는 필터 레코드를 원하는 재활용 뷰를 사용하고 있지만 사용자 정의 키패드와 편집 텍스트 입력을 제공하기 위해 사용자 정의 버튼을 사용하고 있지만 빨리 당신은 내가 맡는다에서 벗어나고 수천의 기록을 가지고하는 데 도움이 될 수 있습니다 버튼을 클릭에 대한 지연을 받고
Sagar

답변:


141

.xml 레이아웃 파일의 목록보기 위에 EditText를 추가합니다. 그리고 당신의 활동 / 조각에서 ..

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

여기서 기본은 편집 텍스트에 OnTextChangeListener 를 추가 하고 콜백 메서드 내에서 목록보기의 어댑터에 필터를 적용하는 것입니다.

편집하다

사용자 정의 BaseAdapter 구현하는 방법 "LL 필요에 필터를 얻으려면 필터링의 인터페이스를.

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

performFiltering () 내부 에서 검색 쿼리를 데이터베이스의 값과 실제 비교해야합니다. 결과를 publishResults () 메서드에 전달합니다 .


BaseAdapter를 확장하는 사용자 지정 어댑터를 만들었고 그 안에 목록에 표시 될 개체의 벡터를 정의했습니다. 위 코드를 사용하려고하면 어댑터에서 getFilter 메서드를 찾을 수 없습니다. 인터페이스를 구현해야하는지 알려주세요. ??
Amira Elsayed Ismail 2013

BaseAdapter의 경우 데이터를 필터링하는 것은 약간 까다 롭습니다. BaseAdapter 구현에 Filterable 인터페이스를 구현해야합니다. 그러면 getFilter () 메서드가 있고 그 안에 작업 할 두 개의 콜백 메서드를 구현해야합니다. void publishResults () 및 FilterResults performFiltering (CharSequence 제약).
Purush Pawar 2013

간단한 예제로 지원해 주시겠습니까?
Amira Elsayed Ismail 2013

예. 내 대답의 편집 섹션을 확인하십시오.
Purush Pawar 2013

1
나는 이것과 관련하여 다른 질문을 게시하는 것이 좋습니다. 같은 게시물에 다른 질문을 계속하는 것은 적절한 방법이 아니기 때문입니다. 글쎄, 먼저 전체 arraylist를 다른 임시 arraylist에 복사하고 onPerformFiltering () 메서드 내부에서 검색을 위해이 임시 목록을 사용합니다. 이것은 당신의 문제를 해결할 것입니다. 그리고 도움이된다면 찬성 및 / 또는 답변을 수락하십시오.
Purush Pawar 2013

9

필터링 가능한 어댑터 구현 :

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

그런 다음 필터 클래스를 만듭니다.

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

}

이렇게하면 어댑터가 필터링 가능하므로 필터 항목을 어댑터의 필터로 전달하고 작업을 수행 할 수 있습니다. 도움이 되셨기를 바랍니다.


1

이 주제에 여전히 관심이있는 경우 목록을 필터링하는 가장 좋은 방법은 일반 필터 클래스를 만들고 Java 구식 SDK 패키지에 포함 된 일부 기본 반사 / 제네릭 기술과 함께 사용하는 것입니다. 내가 한 일은 다음과 같습니다.

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

이후에해야 할 일은 어댑터 참조, 목록 및 필터링을 위해 호출 할 메서드를 전달하는 멤버 클래스 (View의 "onCreate"내에서 가능)로 필터를 만드는 것입니다.

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

지금 누락 된 유일한 것은 어댑터 클래스의 "getFilter"메서드를 재정의하는 것입니다.

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

완료되었습니다! 목록을 성공적으로 필터링해야합니다. 물론 필요를 설명하는 최상의 방법으로 필터 알고리즘을 구현해야합니다. 아래 코드는 단지 예일뿐입니다. . 도움이 되었기를 바랍니다.


나는 안드로이드에 대해 잘 모르지만, 리소스 집약적이기 때문에 가능하다면 C #에서 반사를 피하도록하라는 말을 들었던 기억이납니다. 또는 리플렉션이 제네릭없이 실제 클래스를 빌드하는 것과 동일한 효과가 있습니까? 필터링 가능한 템플릿을 만들고 매개 변수로 사용되는 클래스와 메서드를 추가 할 생각이었습니다
Cruces

네, 맞습니다. 여기서도 마찬가지입니다. 리플렉션은 프로그램 처리에 가중치를 부여하지만이 경우에는 매우 간단하게 사용하고 일반 / 템플릿 표기법과 함께 사용하기 때문에 컴파일러에도 도움이됩니다. 행운을 빕니다!
jbrios777

NB 리플렉션을 사용하면 난독 화 (dexguard / proguard) 문제가 발생할 수 있습니다.
Alexey
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.