본문 바로가기

Android/지식저장소

[Android] ConstraintLayout Helper - Group

group 은 ConstraintLayout 에서 제공하는 helper 중의 하나로, 여러 뷰들의 visibility 를 그룹으로 묶어 편리하게 관리할 수 있게 해준다.

ConstraintLayout 으로 뷰를 구성하다보면 모든 뷰들이 flat하게 존재하기 때문에, visibility 를 한 묶음으로 변경해야할 때 보일러플레이트 코드가 많아질 수 밖에 없다.

iv_remote.visibility = visibility
tv_remote_count.visibility = visibility

iv_vacation.visibility = visibility
tv_vacation_count.visibility = visibility

another_view1.visibility = visibility
another_view2.visibility = visibility
...
another_view{N}.visibility = visibility

이런식으로 관리할 뷰가 많아질수록 코드도 늘어나게되는데, 그래서 이를 묶음으로 관리하기위해 활용할 수 있는 것이 바로 Group 이다.

<androidx.constraintlayout.widget.Group
        android:id="@+id/group_views"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="view1,view2,view3,view4" />

xml 에 위와 같이 선언하고 코드로 group_views.visibility 만 변경해주면 끝!

⚠️ 주의할점
- Group 은 ViewGroup이 아니어서 차일드뷰를 추가하는 느낌으로 구현하는게 아니라, 위와 같이 referenced_ids 에 그룹으로 묶어 관리할 뷰들의 id 를 추가해주어야한다.
- Group 으로 묶어 visibility 를 변경한 후 추가된 View 의 visibility 를 임의로 바꿀 경우 뷰가 이상하게 그려질 수 있다.

공식문서

또 다른 helper 클래스로 Guideline, Barrier, Placeholder 등등이 있다.

group 을 응용한 예시로 수평, 수직으로 구성된 라디오 그룹이 아닌 커스텀 라디오그룹을 만드는 방법도 있는데 여기를 참고해보자.

 

👉🏻 RecyclerView 아이템에서 사용할 때 발견한 오류(는 아니지만 내 기준 버그) 관련 이야기

1. 아이템뷰 xml 에서는 Group이 선언되어있었다. (default visibility 가 View.VISIBLE)

2. 최초 상태에서 뷰 형태가 바뀌어야해서 RecyclerViewAdapter.notifyDataSetChanged() 를 호출해 onBindViewHolder() 가 호출되도록 했다.

3. 뷰홀더들이 새로 생성되면서 Group.visibility = View.VISIBLE 이 됐을거라고 예상했다.

4. onBindViewHolder() 에서 내가 세팅한 값에 의해 Group.visibility = View.GONE 이 들어가야한다. (당연히 xml 보다 코드가 우선이라고 생각했다.)

5. 하지만 visibility 설정이 제대로 되지않았고, 그대로 Group.visibility = View.VISIBLE 로 되어있었다.

6. xml 에서 Group 을 없애버리고 돌려보니 제대로 된다.

7. 그래서 추적해본결과, onBindViewHolder() 가 호출된 후 Group 의 visibility 가 변경되는 것을 발견했다.

8. Group 의 visibility 는 onAttachedToWindow() 에서 변경된다.

9. 그래서 리사이클러뷰에 addView 될 때 onAttachedToWindow() 가 불리면서 xml 에 지정한 Group visibility 가 세팅되는 것이었다.

10. onCreateViewHolder() -> onBindViewHolder() -> LayoutManager.addView() -> Group.onAttachedToWindow() // 최종 visibility는 이 단계에서 결정

위와 같은 순서로 진행되면서, onBindViewHolder() 에서 아무리 visibility 를 지지고 볶아도 최종 모습은 Group 에 세팅된 visibility 로 반영된다는 것..

 

결론 : 웬만하면 하나로 묶어 visibility 를 관리하는 Group 이 있을 경우 소속된 뷰들의 visibility 를 임의로 바꾸지 말자.