ConstraintLayout에는 레이아웃을 구성하기 위한 가상 오브젝트들이 존재한다. 가상 오브젝트란 실제 레이아웃에는 나타나지 않으며, 실제 레이아웃을 배치할 때 좀 더 편리하게 구성할 수 있게 도움을 준다.
1. Guideline
가이드라인은 가로 또는 세로의 축을 가진 가상의 뷰로써, 부모 뷰의 특정 위치를 기준점으로 삼을 때 사용한다. 가로/세로를 적용할 때는 LinearLayout과 같이 android:orientation 옵션으로 설정할 수 있다.
가로/세로를 정했다면 이제 위치를 정해야 한다. 위치를 정하는 옵션으로는 3가지가 있다.
- app:layout_constraintGuide_begin
- app:layout_constraintGuide_end
- app:layout_constraintGuide_percent
app:layout_constraintGuide_begin과 app:layout_constraintGuide_end는 dp와 px과 같이 수치를 적용하는 옵션이고, app:layout_constraintGuide_percent는 퍼센트를 적용하는 옵션이다.
begin은 왼쪽 혹은 위에서 얼마나 떨어져 있는지를 뜻하고, end는 오른쪽 혹은 아래에서 얼마나 떨어져 있는지를 뜻한다. 예를 들어, 세로축으로 해서 begin은 100dp만큼 설정하면 아래와 같이 된다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="100dp"/>
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_end="100dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
percent는 왼쪽 혹은 위에서 어느 정도의 비율만큼 떨어져 있는지를 뜻하며, 값은 0.0부터 1.0까지 설정할 수 있다. 예를 들어, 왼쪽에서부터 30%의 지점에 가이드라인을 설정하고 싶다면 아래와 같이 하면 된다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.3" />
</androidx.constraintlayout.widget.ConstraintLayout>
2. Barrier
배리어는 다국어를 고려해서 레이아웃을 짜야할 때 특히 유용하다. 예를 들어, 세로로 배치된 두 개의 텍스트뷰가 있고, 두 텍스트뷰의 오른쪽에 이미지 뷰를 넣으려고 한다. 상황에 따라 두 텍스트뷰의 길이가 달라질 수 있다면, 이미지 뷰는 어떤 텍스트뷰를 기준으로 삼아야 할까?
이런 상황에서 도움을 주는 것이 배리어다. 배리어는 여러 뷰를 참조하고 지정된 측에서 가장 극단적인 위젯을 기반으로 가이드라인을 만든다.
배리어에서 주로 사용하는 옵션은 app:constraint_referenced_ids와 app:barrierDirection이다. app:constraint_referenced_ids 옵션으로 어떤 뷰를 참조할지를 설정하고, app:barrierDirection 옵션으로 배리어가 참조하는 뷰의 어느 방향에 위치할지를 설정한다.
위의 예시를 코드로 작성하면 아래와 같게 된다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="50dp">
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ABC"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/tv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ABCDEFGHIJKLMNOP"
app:layout_constraintTop_toBottomOf="@id/tv_1"
app:layout_constraintStart_toStartOf="parent"/>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tv_1, tv_2"
app:barrierDirection="end"/>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:background="@color/black"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="@id/barrier"/>
</androidx.constraintlayout.widget.ConstraintLayout>
3. Group
여러 개의 뷰들을 동시에 visible, gone 처리해주려면 어떻게 해야 될까? 하나의 ViewGroup으로 묶어서 해당 ViewGroup의 visibility 속성을 변경하거나, 아래와 같이 함수를 하나 만들어서 모든 뷰의 visibility를 변경할 수 있다.
fun setVisibility(isVisible: Boolean) {
val state = if (isVisible) View.VISIBLE else View.GONE
view1.visibility = state
view2.visibility = state
...
}
만약 관리해줄 뷰가 많아진다면 코드가 길어지고, ViewGroup으로 묶으면 불필요하게 View 계층이 생긴다는 문제가 있다.
Group을 사용하여 여러 개의 뷰들을 그룹화시키면 한 번의 visible 처리로 그룹 안의 모든 뷰들을 동시에 처리해줄 수 있다. 또한 해당 객체는 ConstraintLayout에 계층 구조로 잡히지 않으며 렌더링 되지 않는다.
사용법은 간단하다. app:constraint_referenced_ids 옵션으로 관리해줄 뷰의 id를 추가해준 뒤, group의 visibility를 변경해주면 된다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.constraintlayout.widget.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tv_1, tv_2"/>
</androidx.constraintlayout.widget.ConstraintLayout>
참고
developer.android.com/reference/androidx/constraintlayout/widget/Barrier
developer.android.com/reference/androidx/constraintlayout/widget/Guideline
developer.android.com/reference/androidx/constraintlayout/widget/Group
'Android' 카테고리의 다른 글
[Android] RecyclerView에 divider 넣기 - ItemDecoration (1) | 2021.01.16 |
---|---|
[Android] LiveData setValue() vs postValue() (0) | 2021.01.15 |
[Android] DataBinding - BindingAdapter 활용하기 (0) | 2020.12.26 |
[Android] parent의 영역을 벗어나서 UI를 그려보자 - clipChildren (2) | 2020.12.06 |
[Android] Custom Calendar 만들기 - Infinite ViewPager 구현 (2) | 2020.11.27 |