[Android Studio] 리스트뷰에 검색기능 추가하기

     

안드로이드앱을 만들면서 가장 많이 쓰는 기능중에 하나인 커스텀 리스트뷰에 검색기능을 추가해보겠습니다. 아무래도 일련의 데이터를 나열해주는 리스트뷰이기 때문에 검색기능이 필수적으로 필요한데요.. 검색기능을 넣는 방법은 여러가지가 있지만 여기서는 검색어를 입력하는 EditText창이 변할때마다 리스트뷰가 바뀌는 방식으로 구현해보도록 하겠습니다.



아마 대부분 위와같은 형태의 뷰를 만들지 않을까...? 하고 조심스럽게 추측합니다. ㅎㅎㅎ

검색할수있는 EditText부분과 그 아래 보여지는 커스텀 뷰가 있겠죠. 그럼 어떻게 이 두개를 연결할까요?


여기서는 EditText의 TextChangeListener를 활용합니다. TextChangeListener는 말 그대로 EditText의 입력된 글이 변할때마다 호출되는 CallBack메소드로 TextWatcher라는 인터페이스를 사용할 수 있습니다. TextWatcher는 다음과 같은 내부 메소드를 가지고 있습니다.


Public methods

abstract voidafterTextChanged(Editable s)

This method is called to notify you that, somewhere within s, the text has been changed.

abstract voidbeforeTextChanged(CharSequence s, int start, int count, int after)

This method is called to notify you that, within s, the count characters beginning at start are about to be replaced by new text with length after.

abstract voidonTextChanged(CharSequence s, int start, int before, int count)

This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before.


영어로 되어있지만 메소드 이름만 봐도 어떤역할인지 아실겁니다.. ㅎㅎ after~의 경우 글자가 바뀌고 난후, before는 글짜가 바뀌기 전, on~은 바뀌는 순간에 실행되죠. 이렇게 메소드만 봐서는 머 어떻게하는건지 모르니까 실제로 어떻게 사용하는지 보겠습니다.


et_searchText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {

}

@Override
public void afterTextChanged(Editable s) {
String searchText = et_searchText.getText().toString();
adapter.fillter(searchText);
}
});


여기서 et_searchText는 EditText 객체 입니다. 여기서는 텍스트를 입력하고 난 뒤에 리스트 뷰가 갱신되기 때문에 afterTextChanged 아래 필요한 메소드를 적었습니다. 


일단 커스텀 리스트뷰를 생성하는 것을 알고있다는 가정 하에 진행하도록 하겠습니다.
(혹시 모른다면 참조 - 
http://cholol.tistory.com/300 )


텍스트뷰가 바뀌었을 경우 리스트뷰가 바뀌는 메소드를 filler라는 이름으로 구현하도록 하겠습니다. fillter는 리스트뷰를 뿌려주는 역할을 하는 listviewadapter부분에 생성하게 됩니다.


public void fillter(String searchText) {
displayListItem.clear();
if(searchText.length() == 0)
{
displayListItem.addAll(listItem);
}
else
{
for( BookListItem item : listItem)
{
if(item.getBookName().contains(searchText))
{
displayListItem.add(item);
}
}
}
notifyDataSetChanged();
}

위 코드가 adapter부분에 구현된 fillter메소드입니다. 메소드가 실행되면 인풋인 searchText를 현재 가지고 있는 리스트와 비교하여 리스트의 텍스트가 searchText를 포함하고 있다면 리스트뷰에 보여주도록 짜여있습니다. 여기서 기존 리스트뷰 어댑터와 다른점은 List객체를 두 개를 만들었다는 점입니다.

보통 커스텀리스트뷰를 만들 때, 리스트에 추가하는 List객체는 하나를 사용하는데, 여기서는 listItem이라는 List와 displayListItem이라는 List 두 개를 사용했습니다. listItem의 경우는 실제로 전체의 내용을 담고있는 listItem이며 displayListItem은 리스트뷰를 통해 보여줄 리스트입니다. 이렇게 사용하는 이유는 검색어에 따라 화면에 보여주는 List가 다르기 때문입니다. (검색어가 없을경우 전체를 보여주지만 검색어가 있을경우 전체리스트중에 해당하는 리스트만 보여줘야하기 때문에)

따라서 전체의 리스트를 보여줄때에는 listItem = displayListItem이지만 그외의 경우에는 항상 listItem > displayListItem입니다. 

fillter 마지막에 있는 notifyDataSetChanged()메소드는 리스트뷰의 데이터가 바뀌었으니 갱신해야한다는 것을 리스트뷰에 알리는 메소드입니다.


소스를 적용하고 실행하면 다음과 같이 검색되는 것을 확인 할 수 있습니다.




검색어가 입력되는 순간 리스트뷰가 갱신되는 것을 확인할 수 있습니다~

반응형

댓글

Designed by JB FACTORY