📌 Intro
RecyclerView를 사용하면서 많은 양의 데이터를 보여주게 될 경우 원하는 아이템을 찾기 어려웠고, 특히나 개인 프로젝트를 진행하면서 많이 느꼈다. 이를 해결하기 위해 recyclerView에 검색 기능을 추가하였고 이 방법에 대해 정리하려고 한다.
📌 검색 기능 추가하기
검색 기능을 추가하기에 앞서 아래 글에서 사용한 코드를 가져와 사용하려고 한다.
[Android] RecyclerView 사용하기 2
📌 Intro 이전에는 RecyclerView의 가장 기본적인 사용법에 대해 정리하였다. 하지만 RecyclerView는 다양한 방법으로 사용할 수 있다. 다양한 방법이 있겠지만 나는 개인적으로 진행하고 있는 토이 프
krrong.tistory.com
1. 어댑터 코드 수정(SimpleTextAdapter.java)
public void setItems(ArrayList<SingleItem> list){
items = list;
notifyDataSetChanged();
}
SimpleTextAdapter에 setItems() 함수를 추가로 만들어주자.
이 함수는 어댑터의 아이템을 인자로 받은 아이템으로 바꾸고 notifyDataSetChanged()를 통해 recyclerView에게 데이터가 변했다고 알리는 역할을 한다.
setItems()함수를 추가한 전체 SimpleTextAdapter.java 코드는 다음과 같다.
package com.example.recyclerview;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class SimpleTextAdapter extends RecyclerView.Adapter<SimpleTextAdapter.ViewHolder> {
private ArrayList<SingleItem> items = null;
public class ViewHolder extends RecyclerView.ViewHolder{
TextView text_name;
TextView text_description;
ImageView imageView;
public ViewHolder(@NonNull View itemView) {
super(itemView);
text_name = itemView.findViewById(R.id.text_name);
text_description = itemView.findViewById(R.id.text_description);
imageView = itemView.findViewById(R.id.imageView);
}
}
// 생성자
SimpleTextAdapter(ArrayList<SingleItem> list){
items = list;
}
// 아이템 뷰를 위한 뷰홀더 객체 생성하여 리턴
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.item, parent, false);
SimpleTextAdapter.ViewHolder vh = new SimpleTextAdapter.ViewHolder(view);
return vh;
}
// position 에 해당하는 데이터를 뷰홀더의 아이템 뷰에 표시
@Override
public void onBindViewHolder(@NonNull SimpleTextAdapter.ViewHolder holder, int position) {
String name = items.get(position).name;
String description = items.get(position).description;
int resId = items.get(position).resId;
holder.text_name.setText(name);
holder.text_description.setText(description);
holder.imageView.setImageResource(resId);
}
// 전체 데이터 개수 리턴
@Override
public int getItemCount() {
return items.size();
}
public void setItems(ArrayList<SingleItem> list){
items = list;
notifyDataSetChanged();
}
}
2. activity_main.xml 수정
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="검색어 입력"
android:inputType="textPersonName" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="627dp" />
</LinearLayout>
원래 activity_main.xml은 recyclerView만 가진 상태였지만 검색 기능을 추가하기 위해 editText도 하나 추가해주도록 하자.
3. MainActivity.java 수정
package com.example.recyclerview;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
// 검색시 같은 이름이 있는 아이템이 담길 리스트
ArrayList<SingleItem> search_list = new ArrayList<>();
// recyclerView에 추가할 아이템 리스트
ArrayList<SingleItem> original_list = new ArrayList<>();
// 어댑터
SimpleTextAdapter adapter;
EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 리스트에 아이템 추가
for(int i=0; i<50; i++){
if(i % 2 == 0){
original_list.add(new SingleItem("ITEM " + i,"foreground image " + i,R.drawable.ic_launcher_foreground));
}
else{
original_list.add(new SingleItem("ITEM " + i,"background image " + i,R.drawable.ic_launcher_background));
}
}
editText = findViewById(R.id.editText);
// editText 리스터 작성
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
String searchText = editText.getText().toString();
search_list.clear();
if(searchText.equals("")){
adapter.setItems(original_list);
}
else {
// 검색 단어를 포함하는지 확인
for (int a = 0; a < original_list.size(); a++) {
if (original_list.get(a).name.toLowerCase().contains(searchText.toLowerCase())) {
search_list.add(original_list.get(a));
}
adapter.setItems(search_list);
}
}
}
});
// 리사이클러뷰, 어댑터 연결
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new SimpleTextAdapter(original_list);
recyclerView.setAdapter(adapter);
}
}
editText에 대한 이벤트 리스너를 작성할 수 있다. 콜백 함수들은 다음과 같다.
- void beforeTextChanged(CahrSequence s, int start, int count, int after)
s문자열이 start위치로부터 count길이만큼이 after길이로 변경되려고 한다는 내용을 전달해주면서 호출된다. - onTextChanged(CharSequence s, int start, int before, int count)
s가 start위치로부터 count길이만큼 변경되었다는 것을 알려준다. 이전 문자열에서 before길이만큼 바뀌었다는 것을 알려준다. - afterTextChanged(CharSequence s, int start, int before, int count)
s내의 어느 문자열이 변경되었다는 것을 알려주기 위해 호출된다. s를 변경할 시 다시 재호출이 되기 때문에 무한루프에 빠질 가능성이 있으니 주의해야 한다.
위 세개의 콜백 함수 중 afterTextChanged()함수를 사용하여 원하는 검색 기능을 구현할 수 있다.
아이템을 저장하고 있는 리스트를 순회하면서 사용자가 editText에 작성한 문자를 포함하고 있는지 확인한 뒤, 포함하는 아이템들을 search_list라는 새로운 리스트에 담고, setItems()함수를 통해 어댑터의 아이템을 바꿔주면 된다.
4. 실행화면
- 기본 실행 화면
- 검색 화면
많은 데이터에서 내가 필요한 정보만을 찾기 위해 recyclerView에서 editText를 활용하여 검색하는 기능을 구현해보았다.
📌 Github
전체 코드는 Github 링크 에서 확인할 수 있다.
📌 참고
[1] https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=777lover&logNo=10131263714 (editText 이벤트 리스너)
[2] https://stickode.tistory.com/49 (검색 기능 구현 코드)