조금 더 복잡한 RecyclerView Multi ViewHolder

PathoS
3 min readOct 26, 2020

--

담당했던 앱의 일부 화면은 SDUI로 구현되어 있다. 초기에는 비교적 단순한 구조여서 LinearLayoutManager 만으로도 처리가 가능했지만, 좀 더 복잡한 조건의 컴포넌트가 추가되면서 이를 처리하고자 했던 경험을 정리하려고 한다.

제약조건

  1. 다양한 종류의 컴포넌트가 존재
  2. 하나의 RecyclerView를 이용해서 구현할 것
  3. 인접하는 컴포넌트 종류에 따라 간격이 달라짐

다양한 종류의 컴포넌트

실제 회사앱에서는 더 많은 종류의 컴포넌트가 존재했지만, 예제를 단순화 하기 위해 컴포넌트는 3개만 표현한다. 각각의 컴포넌트 들은 아래와 같다.

  1. TITLE의 경우 단순 텍스트를 보여주는 컴포넌트
  2. GALLERY는 여러개의 이미지를 수평 스크롤이 가능한 컴포넌트
    (중첩된 RecyclerView)
  3. PARTNER는 업체정보를 Grid형태로 화면의 절반을 차지하는 컴포넌트
    (이미지하나와 텍스트뷰 하나로 구성)

요구사항 구현

구현에 대한 설명은 프로젝트 생성부터 모두 설명하는게 아닌 요구사항 구현과 연관된 부분만 집중해서 설명하도록 하겠다. 그래서 앱 구조적인 부분도 최대한 단순화해서 구현했다. 글에 사용된 코드는 여기서 확인할 수 있다.

LayoutManager

기존에 LayoutManger 중 요구사항에 제일 가까운건 GridLayoutManager이기 때문에 여기서부터 시작하기로 한다.

여기서 각 아이템 마다 spanSize를 설정 할 수 있다면 쉽게 문제를 해결 할 수 있을꺼 같았다. 찾아보니 SpanSizeLookup 을 통해서 설정이 가능하다. 😎

PARTNER 컴포넌트만 spanSize를 1로 조정해준다.

여기까지 중간 결과물

컴포넌트간 간격

기존에는 리스트의 시작,끝, 아이템사이 간격정도만 RecyclerView.ItemDecorator를 사용했었다. 여기에 검사 조건은 넣어 인접한 컴포넌트의 종류에 따라 간격이 달라지게 작업해 보자.

컴포넌트 마진 조건

  1. top margin은 30dp로 고정.
  2. bottom margin은 60dp. 단 FOOTER 컴포넌트가 마지막인 경우 0dp.
    (이 단계에서 간단하게 FOOTER 컴포넌트를 추가한다.)
  3. TITLE 컴포넌트 다음에 GALLERY 컴포넌트면 사이간격은 5dp
  4. TITLE 컴포넌트 다음에 PARTNER 컴포넌트인 경우 사이 간격은 10dp
  5. 기본 간격은 20dp

여기서 중요한건 하나의 컴포넌트가 무조건 하나의 row를 차지하는게 아니기 때문에, 다음 컴포넌트를 찾을 때 현재위치+1은 정확하지 않다.

그래서 각 컴포넌트의 row 위치를 구한 다음, 다음 row의 컴포넌트 타입이 무엇인지 구해서 조건을 검사해야 한다. 그러기 위해 필요한 값들을 구한다.

이제 조건에 맞게 간격을 세팅한다.

추가로 수평 간격도 세팅해 준다.

최종 결과물

정리

작업할 때만해도 꽤 쓸만한 정보라고 생각했는데, 글로 정리하고 나니 그렇게 유익한 정보는 아닌거 같다. 다시한번 글에 사용된 코드는 여기서 확인할 수 있다.

--

--