리싸이클러뷰 멀티 뷰타입 사용해보기

2021. 1. 10. 17:02android

 

뷰타입(view type)이란, 리싸이클러뷰를 구성하는 리스트들의 타입을 구분짓는 용도로 사용됩니다. 예를들면 카카오톡처럼 좌, 우 대화창이 나오는 구조는 각각의 뷰 타입을 갖는 뷰홀더를 생성하는 것이 편합니다. 따라서 오늘은 카카오톡과 비슷한(?) 채팅 기능을 만들어보겠습니다.

1. 기본 설정


저는 기본적으로 앱 개발을 할 때, dataBinding을 많이 사용합니다.

 

첫번째 이유는 안드로이드 최신 버전부터 'kotlin-extension'을 사용함으로써 발생하는 여러 문제들로 인해,

gradle default setting에서 제외되었기 때문입니다. 사용하려면 이제 gradle에 직접 추가해줘서 사용해야합니다. 이렇게 구글이 배척하는 건 다 이유가 있다고 생각하기에..전 kotlin-extension을 사용하지 않습니다.

 

두번째 이유는 dataBinding을 사용할 시, xml에 변수값을 넘겨줄 수 있습니다. 이는 mvvm패턴에서 필수적인 요소이기도 하며, 데이터를 셋팅하는 부분을 xml에서 할 수 있으니, 코드가 깔끔해지기때문입니다. 

 

dataBinding을 추가하기 위해서 app단의 gradle에서 위의 그림처럼 셋팅해줍니다. 만약 에러가 난다면 plugins에 'kotlin-kapt'을 추가해주세요.

2. 구성 화면


 

메인 화면의 기본적인 구성입니다. 화면 대부분을 차지하는 부분은 

recyclerview이고 하단쪽에는 글을 쓰기위한 editText와 글을 전송하기

위한 버튼이 한개 존재합니다. 

 

앞서 말한바와 같이, 카카오톡과 비슷한 채팅 기능을 만들기 위해서 왼쪽과

같은 화면을 구성했습니다.

 

 

 

 

 

 

 

 

 

 

3. 리스트 item 구성화면


리싸이클러뷰에서 보여지는 값은 좌측 말풍선, 우측 말풍선입니다. 따라서 각각에 대한 xml이 존재해야 합니다.

 

- Left

- Right

4. list item model class


뷰타입을 결정 짓는 요소는 바로 리스트 아이템입니다. 따라서 리스트를 구성하는 item model class를 하나 만듭니다.

 

priority constructor를 통해서 talkContent와 type property를 생성해줍니다. 두 프로퍼티는 입력한 값을 저장하기 위한 talkContent와 어댑터에서 뷰타입을 구분지을 수 있도록 하기 위한 type으로 구성되어 있습니다.

 

추가적으로 data 키워드를 사용한 이유는 상속받은 toString()등의 몇몇 상속받은 값들을 자동으로 프로퍼티에 대한 내용으로 만들어주기 때문에 사용했습니다. (data 키워드를 사용하지 않아도 되지만 일반적으로 model class는 할당된 값을 확인하기 위해서 toString()를 많이 사용하기에 data 키워드를 같이 사용하는게 일반적인 방법입니다.)

5. 어댑터


멀티 뷰타입에서 가장 중요한 것은 뷰타입에 따른 뷰홀더입니다. 여기서는 좌, 우에 대한 뷰타입 2개만 있음으로 뷰홀더 또한 2개가 존재해야 합니다. 

 

전반적인 리싸이클러뷰 어댑터의 흐름은 리스트를 파라미터로 받아옵니다. 그럼 어댑터는 리스트의 element들을 하나한 꺼내서 뷰타입을 확인하여, view객체를 만들고 이를 viewholder로 넘겨줍니다.

 

이러한 전반적인 흐름을 멀티뷰 타입을 사용한다고 해서 완전히 벗어나지 않습니다. 다만 하나의 뷰타입을 사용했을 때는 모두 동일한 뷰타입이기 때문에 핸들링할 필요가 없었지만 멀티뷰 타입을 사용하게 되면 뷰타입을 핸들링할 수 있어야합니다. 따라서 getItemViewType(position: Int) 메서드를 overriding 해야합니다!! 

 

getItemViewType() 메서드에서 item model class에서 정의한 type프로퍼티를 통해서 하나하나 뷰타입을 나눌 수 있도록 정의합니다. 코드에서 볼 수 있는 것처럼 type이 left면 0을 리턴하고, right면 1을 리턴하도록 핸들링했습니다.

 

이렇게 리턴한 값은 oncreateViewHolder() 메서드의 파라미터인 viewType으로 들어오게 됩니다. 따라서 oncreateViewHolder()에서 파라미터 값인 viewType에 따라 viewHolder를 생성해 주면 됩니다.

6. mainActivity


editText에서 입력한 값을 받아오기 위해서 textWatcher를 overriding합니다. 그렇게해서 얻어온 실시간 입력 값을 전역변수인 s에 저장합니다.

 

이후 '보내기' 버튼을 클릭하면 리싸이클러뷰에 값을 추가하도록 합니다. 이 역할을 하는 메서드가 바로 submitTalk()입니다. 카카오톡과 같은 대화화면을 만들기 위해서 item model class의 type을 좌, 우로 번갈아서 지정했습니다. 

 

추가적으로 smoothScrollToPosition()메서드를 사용한 이유는 대화가 많아져 화면을 넘어가게 되면 스크롤이 생기게 됩니다. 그런데 스크롤을 수동적으로 내려야만 계속해서 대화글이 보여지게 되므로 자동 스크롤 기능을 넣은 것입니다.

 

마지막으로 '보내기' 버튼 클릭 시, edittext를 쓴 글을 비워주기 위해서 editText.text =null로 설정합니다.

 

7. 결과


'android' 카테고리의 다른 글

코루틴이란?  (2) 2021.04.29
Glide란?  (0) 2021.01.18
recyclerView와 dataBinding 같이 사용하기  (1) 2021.01.03
Observer pattern 구조 및 사용  (0) 2020.12.27
SINGLE_TOP, CLEAR_TOP,NEW_TASK로 액티비티 task 관리하기  (0) 2020.12.13