Android에서 ListView를 동적으로 업데이트하는 방법 [닫기]


159

Android ListView에서 사용자 입력을 기반으로 필터링하여 표시된 항목이 TextView값을 기준으로 동적으로 업데이트되는 방법은 무엇입니까?

나는 이와 같은 것을 찾고있다 :

-------------------------
| Text View             |
-------------------------
| List item             |
| List item             |
| List item             |
| List item             |
|                       |
|                       |
|                       |
|                       |
-------------------------

7
재개를 추천합니다. 이 질문을 더 많이하기 위해 텍스트를 업데이트했으며, 답변이 계속 나오면서 귀중한 커뮤니티 리소스입니다.
Hamy

질문을 다시여십시오. 분명히 도움이됩니다.
SilentNot

답변:


286

먼저 EditText와 ListView가 모두있는 XML 레이아웃을 만들어야합니다.

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <!-- Pretty hint text, and maxLines -->
    <EditText android:id="@+building_list/search_box" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="type to filter"
        android:inputType="text"
        android:maxLines="1"/>

    <!-- Set height to 0, and let the weight param expand it -->
    <!-- Note the use of the default ID! This lets us use a 
         ListActivity still! -->
    <ListView android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1" 
         /> 

</LinearLayout>

이것은 ListView 위에 멋진 EditText를 사용하여 모든 것을 올바르게 배치합니다. 다음으로, 평상시처럼 ListActivity를 작성하지만 메소드에 setContentView()호출을 추가하여 onCreate()최근에 선언 된 레이아웃을 사용하십시오. 우리는으로 ListView특별히 ID를 정했습니다 android:id="@android:id/list". 이를 통해 선언 된 레이아웃에서 사용할 ListActivity것을 알 수 있습니다 ListView.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.filterable_listview);

        setListAdapter(new ArrayAdapter<String>(this,
                       android.R.layout.simple_list_item_1, 
                       getStringArrayList());
    }

앱을 실행하면 ListView위의 멋진 상자와 함께 이전이 표시 됩니다. 그 상자가 무언가를하게하려면, 우리는 그것으로부터 입력을 받아서 그 입력이리스트를 필터링하도록해야합니다. 많은 사람들이이 작업을 수동으로 시도했지만 대부분의 ListView Adapter 클래스 Filter에는 필터링을 자동으로 수행하는 데 사용할 수 있는 개체가 있습니다. 입력을에서 EditText로 파이프하면 됩니다 Filter. 꽤 쉽다는 것이 밝혀졌습니다. 빠른 테스트를 실행하려면이 회선을 onCreate()통화에 추가하십시오.

adapter.getFilter().filter(s);

ListAdapter이 작업을 수행하려면 변수에 변수 를 저장해야 합니다. ArrayAdapter<String>이전에 '어댑터'라는 변수에 내 변수를 저장했습니다 .

다음 단계는에서 입력을 얻는 것 EditText입니다. 실제로 약간의 생각이 필요합니다. 에를 추가 할 OnKeyListener()수 있습니다 EditText. 그러나이 리스너는 일부 주요 이벤트 만 수신 합니다 . 예를 들어 사용자가 'wyw'를 입력하면 예측 텍스트에 'eye'가 권장 될 수 있습니다. 사용자가 'wyw'또는 'eye'를 선택할 때까지 OnKeyListener주요 이벤트를받지 못합니다. 어떤 사람들은이 솔루션을 선호 할 수도 있지만 실망 스럽습니다. 모든 주요 이벤트를 원했기 때문에 필터링 여부를 선택할 수있었습니다. 해결책은입니다 TextWatcher. 간단하게 생성하고 추가 TextWatcher받는 사람 EditText, 그리고 통과 ListAdapter Filter필터 요청을 텍스트 변경 때마다. 제거하는 것을 잊지 TextWatcher에서를 OnDestroy()! 최종 해결책은 다음과 같습니다.

private EditText filterText = null;
ArrayAdapter<String> adapter = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.filterable_listview);

    filterText = (EditText) findViewById(R.id.search_box);
    filterText.addTextChangedListener(filterTextWatcher);

    setListAdapter(new ArrayAdapter<String>(this,
                   android.R.layout.simple_list_item_1, 
                   getStringArrayList());
}

private TextWatcher filterTextWatcher = new TextWatcher() {

    public void afterTextChanged(Editable s) {
    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
    }

    public void onTextChanged(CharSequence s, int start, int before,
            int count) {
        adapter.getFilter().filter(s);
    }

};

@Override
protected void onDestroy() {
    super.onDestroy();
    filterText.removeTextChangedListener(filterTextWatcher);
}

7
이 솔루션과 같이 "시작"방식 대신 "포함"으로 ListView를 필터링하는 간단한 방법이 있습니까?
Viktor Brešan

12
Viktor-관심있는 단어가 공백으로 구분되면 자동으로 수행됩니다. 그렇지 않으면 실제로는 아닙니다. 아마도 가장 쉬운 방법은 어댑터를 확장하여 서브 클래스 화하고 getFilter 메소드를 대체하여 정의한 Filter 오브젝트를 리턴하는 것입니다. 참조 github.com/android/platform_frameworks_base/blob/master/core/...을 이이 코드 변경 라인 479 및 486의 95 % 복사하는 간단한 것 - 어떻게 기본 ArrayFilter의 작품을 이해하기
HAMY

2
하미, 훌륭한 글쓰기! 나는 질문이있다 : 나는 이것을 구현하고 입력 한 각 문자 후에 ListView가 몇 초 동안 사라지고 다시 돌아와서 필터링된다. 이것을 경험 했습니까? 내 직관은 그것이 사소한 toString () 함수와 함께 목록에 600 개 이상의 항목이 있기 때문입니다.
lowellk

2
작은 화면의 가로 모드에서는 EditText + 키보드가 전체 화면을 차지하며 ListView가 표시되지 않습니다! 어떤 해결책?
Martin Konicek

4
이것이 정말로 필요한가? > OnDestroy ()에서 TextWatcher를 제거해야합니다
Jojo

10

프로그램을 실행하면 강제 종료됩니다.

나는 줄을 바꿨다.

android : id = "@ + building_list / search_box"

android : id = "@ + id / search_box"

그게 문제가 될 수 있습니까? '@ + building_list'는 무엇입니까?


Johe, R.id.something을 말할 때 android : id = "@ + id / search_box"라고 말했기 때문에 id에 문제가 있습니다. android : id = "@ + building_list / search_box"라고 말하면 코드에서 findViewById (R.building_list.search_box); 최고 수준의 예외는 무엇입니까? 이 코드는 테스트 컴파일과 함께 복사되므로 어딘가에 적어도 하나 이상의 오류가 발생했을 가능성이 있습니다
Hamy

안녕하세요, 코드에서 "filterText = (EditText) findViewById (R.id.search_box);"를 사용하여 코드에서 "@ + building_list / search_box"를 참조했습니다. 그게 내가 궁금했던 이유입니다.
j7nn7k

1
입력을 시작할 때 강제 종료가 발생합니다. 오류의 일부 : ERROR / AndroidRuntime (188) : java.lang.NullPointerException 02-11 07 : 30 : 29.828 : ERROR / AndroidRuntime (188) : at xxx.com.ListFilter $ 1. onTextChanged (ListFilter.java:46) 02-11 07 : 30 : 29.828 : ERROR / AndroidRuntime (188) : at android.widget.TextView.sendOnTextChanged (TextView.java:6102) 02-11 07 : 30 : 29.828 : ERROR / AndroidRuntime (188) : android.widget.TextView.handleTextChanged (TextView.java:6143) 02-11 07 : 30 : 29.828 : ERROR / AndroidRuntime (188) : at android.widget.TextView $ ChangeWatcher.onTextChanged (TextView.java : 6286)
j7nn7k

Johe, Oops-@ + building_list를 제거하기 위해 코드를 수정하려고하는 것 같습니다 (혼란의 여지가 있기 때문에) 나는 어디서나 그것을 잡지 못했습니다. 팁 고마워! @ + id로 변경하면 문제가 해결됩니다.
Hamy

4

필터링에 문제가있어 결과가 필터링되었지만 복원되지 않았습니다 !

필터링 (활동 시작) 전에 목록 백업을 만들었습니다. (동일한 데이터를 포함하는 다른 목록)

필터링시 필터 및 목록 어댑터가 기본 목록에 연결됩니다.

그러나 필터 자체는 백업 된 목록의 데이터를 사용했습니다.

내 경우에는 목록이 즉시 업데이트되고 검색 문자를 삭제하더라도 모든 경우에 목록이 성공적으로 복원됩니다.

어쨌든이 솔루션에 감사드립니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.