SearchView-Filter (with Kotlin)

Purang·2022년 9월 22일
0

Android Studio

목록 보기
14/28

저번에 공부했던 SearchView 중 menu로 만든 SearchView 말고 public class SearchView를 통해 Filter를 구현해보고자 합니다.

우선 레이아웃은

<SearchView
        android:id="@+id/searchView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:iconifiedByDefault="false"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/searchView"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        tools:listitem="@layout/post_item"/>

이런 식으로 listitem의 post_item은 저번 포스트에 RecyclerView의 listitem과 동일합니다.

먼저 Filter생성 전에 검색을 위한 data class Post를 작성해줍니다.

data class Post(
    var no : Int, //post 순서
    var email : String, //post 이메일
    //var imageUri : String
)

email을 통해 검색을 시도하기 위해 data class 생성 후
Adapter를 생성합니다.

adapter는 RecyclerView를 생성하는 것 처럼 만들어주는데
중요한 점은

class PostContentAdapter (var post : ArrayList<Post>, var con : Context)
    : RecyclerView.Adapter<PostContentAdapter.postViewHolder>(), Filterable  {

위 처럼 Filterable를 작성해줍니다. 그런 후 멤버를 추가해 주고 난 후

//PostFilter()로 따로 filter함수 작성
var postFilter = PostFilter()

override fun getFilter(): Filter {
            return postFilter
        }

필터를 따로 함수로 작성해보도록 하겠습니다.

inner class PostFilter : Filter() {
			// 입력받은 문자열에 대한 처리
            override fun performFiltering(constraint: CharSequence): FilterResults {
                val filterString = constraint.toString()
                val results = FilterResults()

                //검색이 필요없을 경우를 위해 원본배열 복제
                val filterList : ArrayList<Post> = ArrayList<Post>()

                //공벡제외 아무런 값도 입력하지 않았을 경우 ->원본배열
                if (filterString.trim { it <= ' '}.isEmpty()) {
                    //필터링 작업으로 계산된 모든 값
                    results.values = post
                    //필터링 작업으로 계산된 값의 수
                    results.count = post.size
                    return results

                    //20글자 수 이하일 때 -> 이메일로 검색
                } else if (filterString.trim {it <= ' '}.length <= 20) {
                    for (searchEmail in post) {
                        if (searchEmail.email.contains(filterString)) {
                            filterList.add(searchEmail)
                        }
                    }
                }
                results.values = filterList
                results.count = filterList.size

                return results
            }
			
            //처리에 대한 결과물
            @SuppressLint("NotifyDataSetChanged")
            override fun publishResults(constraint: CharSequence?, results: FilterResults) {
                filterPost.clear()
                filterPost.addAll(results.values as ArrayList<Post>)
                notifyDataSetChanged()
            }
        }

멤버 메소드 중 performFiltering, publishResults를 작성하는데 주석을 보시면 어떠한 곳에 쓰이는 지 알 수 있습니다.

여기서 CharSequence가 궁금했었는데 여기에서 자세히 확인 해볼 수 있습니다.

간단하게 적자면
String : String 객체에 입력되는 문자열 작성된 후 변경할 수 없으며, 문자열은 유니코드로 변형되므로 HTML과 같은 마크업 문자를 입출력할 때 문제가 발생한다. 이와 같이 마크업 문자를 입력하여 사용할 수 없기 때문에 변경할 수 없는 문자열이라고도 부릅니다.

CharSequence : CharSequence 객체에 보관하는 문자열은 같은 유니코드라도 마크업 문자를 사용할 수 있습니다.

그 다음으로 MainActivity에서 검색 버튼에 입력을 확인할 리스너를 만들기 위해 존재하는게 바로
setOnQueryTextListener 입니다. 자세한 것은 참조인 공식사이트에서 확인 하실 수 있습니다.

var searchViewTextListner : SearchView.OnQueryTextListener =
        object :SearchView.OnQueryTextListener {
            //검색버튼 입력시 호출하는데, 지금은 검색버튼이 없으므로 사용x
            override fun onQueryTextSubmit(query: String?): Boolean {
                return false
            }

            //텍스트 입력/수정 시 호출
            override fun onQueryTextChange(s: String?): Boolean {
                mAdapter!!.filter.filter(s)
                return false
            }

        }

이메일 세팅

fun temp() : ArrayList<Post> {
        var t = ArrayList<Post>()
        t.add(Post(1, "wpqkf@gmail.com"))
        t.add(Post(2, "ehofk@gmail.com"))
        t.add(Post(3, "gngk@gmail.com"))
        t.add(Post(4, "gmgl@gmail.com"))

        return t
    }

그 후 adapter연결, 데이터 세팅을 끝내고 실행을 하면
위 데이터 중 w를 가진 view만 나온 것을 확인할 수 있었습니다.

현재는 여기 코드를 따라하면서 이해하려 노력하고 있는데, 다음에는 공부한 내용을 바탕으로 저 만의 SearchView를 구현하도록 열심히 하겠습니다!

profile
몰입의 즐거움

0개의 댓글