일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- rxjava cold observable
- 객체
- 안드로이드 레트로핏 사용법
- 안드로이드 라이선스
- Rxjava Observable
- 안드로이드 os 구조
- android retrofit login
- android ar 개발
- 자바 다형성
- 안드로이드 유닛테스트란
- 안드로이드 유닛 테스트
- jvm 작동 원리
- 안드로이드 레트로핏 crud
- 안드로이드 라이선스 종류
- rxjava hot observable
- ar vr 차이
- 큐 자바 코드
- ANR이란
- 서비스 쓰레드 차이
- 스택 큐 차이
- 클래스
- rxjava disposable
- 서비스 vs 쓰레드
- 멤버변수
- 2022 플러터 안드로이드 스튜디오
- 안드로이드 유닛 테스트 예시
- 2022 플러터 설치
- 플러터 설치 2022
- jvm이란
- 스택 자바 코드
- Today
- Total
나만을 위한 블로그
[Android] 리사이클러뷰 클릭 이벤트 본문
참고한 블로그 : https://thepassion.tistory.com/301
RecyclerView는 선택된 아이템의 선택상태나 선택된 아이템 리스트 관리등의 기능을 제공하지 않는다.
이 글에선 아이템이 선택됐을 때 배경색을 변경하거나 리사이클러뷰 외부에서 선택 or 해제 처리를 하는 법에 대해 정리한다.
1. 특정 아이템 클릭 시 배경색상 변경
먼저 생각해 볼 수 있는 건 아이템이 클릭됐을 때 onClick() 리스너에서 itemView의 배경색을 바꾸는 것이다.
뷰홀더가 보관하는 itemView에 onClick 리스너를 설정했으므로, onClick() 리스너에서 넘어오는 View는 ViewHolder.itemView 객체다.
따라서 아래와 같이 배경색을 변경해 줄 수 있다.
선택 해제 처리는 onClick 이벤트 발생 시 클릭된 아이템의 position(ViewHolder.getAdapterPosition())과 선택 상태를 지정해놓고 토글시키는 방식을 썼다.
position 별 선택 상태를 저장하는 구조는 SparseBooleanArray라는 걸 썼다고 한다.
※ SparseBooleanArray : 구글 검색 시 "다중 삭제" 라는 키워드가 나온다. 이것은 리스트뷰에서 다중 선택 시 선택한 position에 대한 정보를 보관하는 객체고 get()을 호출해 선택된 position의 값을 구한다. get()은 해당 position에 값이 존재하면 true를 반환한다.
기본적으로 int를 boolean에 매핑한다. 즉 int를 키값, boolean을 value값으로 하는 맵과 같다. 이 방법은 HashMap을 써서 정수를 boolean에 매핑하는 것보다 효율적인 방법이다.
※ 디벨로퍼의 SparseBooleanArray : 정수를 boolean으로 매핑한다. 일반적인 boolean 배열과 달리 색인에 공백이 있을 수 있다. 이 기능은 HashMap을 써서 정수를 boolean에 매핑하는 것보다 메모리 효율성이 뛰어나다. 즉, 키밸류가 자동 박스화되는 걸 막고, 각 매핑에 대해 데이터 구조가 추가 입력 개체에 의존하지 않는다.
이 컨테이너는 2진수 검색을 써서 키를 찾으며 배열 데이터 구조에 매핑을 유지한다. 이 구현은 많은 항목을 포함할 수 있는 데이터 구조에 적합하지 않다. 검색에는 2진 검색이 필요하며 추가/제거에는 배열에 항목을 삽입 or 삭제해야 하므로, 일반적으론 기존 HashMap보다 느리다. 수백 개의 아이템들을 holding하고 있는 컨테이너는 성능 차이가 50% 미만으로 특별히 차이나진 않는다.
키(int)와 밸류(int)를 써서 이 컨테이너의 아이템 위로 반복(iterate)할 수 있다. 키(int)를 써서 인덱스의 오름차순으로 키를 반복하면 키가 오름차순으로 반환되거나 밸류(int)의 경우 키에 해당하는 밸류가 오름차순으로 반환된다.
리사이클러뷰 어댑터는 전체 아이템 개수에 기반해 적정수(한 화면에 표시되는 아이템 수 + 스크롤 시 사용할 여분의 아이템 개수)의 뷰홀더(View)를 미리 생성하고, 화면 상 표시되지 않는 뷰를 재사용하는 구조다.
클릭할 때의 뷰가 계속 같은 데이터를 표시한다고 보장할 수 없는 것이다. 즉, 아이템의 선택 상태는 position 기반으로 관리하되, 실제 선택 상태를 표시하는 건 뷰홀더에 데이터가 반영되는 시점에 처리해주면 될 것 같다.
뷰홀더의 getAdapterPosition()은 뷰홀더 재사용 여부와 상관없이 아이템 배치순서 상의 position(제로 베이스)을 리턴한다. DataSet 내의 인덱스 값이라고 생각해도 된다.
그러면
1. 아이템 클릭 시 선택 상태 저장 및 선택 상태 표시
2. 아이템 바인딩 시 선택 상태 표시
순서의 방법으로 구현해보면 될 것 같다.
(중략)
아이템 선택 상태가 변경되는 시점(아이템 클릭 이벤트 발생 or 아이템 선택/해제 메서드가 호출됐을 때)에 선택 상태를 저장(갱신)하고 데이터가 뷰에 바인딩되는 시점인 onBindViewHolder()에서 배경색을 바꾸도록 처리하면 될 것 같다.
다만 onBindViewHolder()가 호출되는 시점은 뷰에 데이터를 바인드해야 하는 상황이므로, 어댑터에게 데이터를 재바인딩해야 함을 알려줘야 한다. 코드 상으로는 setData() 메서드의 notifyDataSetChanged()가 그러하다.
리사이클러뷰 어댑터는 표시되는 데이터를 리바인딩해야 하는 상황에서 어댑터에게 이를 알려줄 수 있도록 notify~ 종류의 메서드를 제공한다. 데이터가 변경된 건 아니지만 강제로 데이터를 다시 그리도록 처리하는 일종의 트릭이다.
백그라운드의 색을 바꾸는 부분은 xml을 통해 처리할 수 있다. xml selector에 select된 상태, select되지 않은 상태에 적용할 색 or 이미지를 지정하고 대상 위젯의 백그라운드 속성으로 해당 selector를 할당하는 방식이다.
여기선 drawable 폴더 밑에 선택 상태에 따라 표시할 색을 지정하는 item_selector.xml을 작성했다.
또한 배경색으로 쓸 색상은 color.xml에 미리 지정해놔야 한다. 그 후 아이템을 표시할 레이아웃의 루트(최상위) 레이아웃에 백그라운드 속성(android:background)을 위 파일로 @drawable/item_selector로 지정해주면 된다.
그리고 onBindViewHolder()에서 코드를 아래처럼 수정하면 선택 상태에 따라 자동으로 배경색이 바뀐다.
롱클릭 이후 데이터를 선택하게 하거나 단일 선택 등 처리는 여기서 좀 응용하면 가능할 것 같다고 한다.
'Android' 카테고리의 다른 글
[Android] FloatingActionButton(플로팅 버튼) (0) | 2019.11.13 |
---|---|
[Android] 리사이클러뷰 클릭 이벤트 2 (0) | 2019.11.07 |
[Android] 파이어베이스를 활용한 앱 채팅 기능 구현 (0) | 2019.11.07 |
[Android] 액티비티에 십자 구분선 넣기 (0) | 2019.11.07 |
[Android] 스플래시 액티비티 만드는 법 (0) | 2019.11.05 |