[Kotlin] 안드로이드 ConstraintLayout 사용법 바르게 쉽게 쓰기! - 구조잡기

2020. 10. 22. 04:23개발/[Kotlin] 안드로이드 개발

반응형

이 포스팅은 학부생이 포스팅하는 것으로 정답이 아닐 수 있음을 밝힙니다.

 

안녕하세요! 안드로이드 첫 포스팅입니다. 

제가 했던 프로젝트를 하나 씩 살펴보는 포스팅과 개념 정리 위주 포스팅 중 어떤 걸 해야 할지 고민을 했었는데요.하나씩 개념을 정리하고 나중에 프로젝트를 하나씩 포스팅 하려고 해요 ㅎㅎ저의 깃허브는 https://github.com/YuYangWoo 이고요.궁금하신점 있으시면 댓글 달아주시면 빠르게 답변 해드리겠습니다! 

 

자! 이제 ConstraintLayout 바르게 쓰기 포스팅 시작하겠습니다.우선 여러분들은 레이아웃을 꾸밀 때 어떤 식으로 하시나요?

자 다음과 같은 레이아웃이 있습니다. 이 레이아웃에는 몇개의 ConstraintLayout이 들어갈까요??

-> 안드로이드 초보 : 하나 두고 그냥 Design 탭에서 위젯 하나씩 가져오면 되는거아닌가요?

틀렸습니다. 그렇게 되면 휴대폰의 크기에 따라 개발자가 원하는 방식으로 View가 나오지 않습니다.

왜냐하면 100dp를 떨어트려도 어느 휴대폰은 화면이 커서 반도 안될 수 있고 어느 휴대폰은 화면이 작아 반 이상이 될 수 있기 때문입니다.

자 그럼 왜 ConstraintLayout을 쓸까요?

한 동안 많이 사용했던 LinearLayout이 ConstraintLayout 밀리게 된 이유는 스마트폰의 다양한 화면에 비율에 따라 매치하기가 힘들기 때문입니다. (LinearLayout을 아예 안쓰는건 아닙니다.)

그러면 ConstraintLayout을 어떻게 사용하는지 알아보도록 하겠습니다.

cstLyMain안에 3개의 cstLy가 더 있습니다.

메인 cstLy로 화면 전체를 잡아주고 top과 mid 그리고 bottom으로 나눴습니다.

보기 쉽게 bluePrint로 보여드릴께요

자 여기서 중요합니다. 왜 그냥 하나의 cstLy로 위젯을 안옮기고 이렇게 3개로 나눴을까요?

바로 휴대폰 마다 크기가 다른 점을 각 ConstraintLayout마다 비율을 잡아줘서 완벽하게 보이기 위함입니다!

 

한 번 화면을 따라해볼께요!

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cstLyTop"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_percent="1.0">

    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cstLyMid"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.3"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/cstLyTop"
        app:layout_constraintWidth_percent="1">

    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cstLyBottom"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/cstLyMid"
        app:layout_constraintWidth_percent="1.0">

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

자 직접 코드를 보시는게 이해가 빠르실거 같아서 가지고 왔습니다.

일단 중요한점 몇 가지를 말씀드리면...

1. 네이밍은 확실하게 정확하게 해야 한다. (의미가 있게)

2. layout_width값과 layout_height값은 0dp로 설정해야 constraint에 매치되어 구조가 잡힌다.

정도 입니다.

살짝 생소하실 수 있어 설명 드리자면 app:layout_constraintEnd_toEndOf="parent"는  constraint의 끝 (오른쪽)은 끝과 맞춘다 -> 어디에? 부모 레이아웃에

위 그림을 보시면 확 이해가 되실겁니다. 

그렇다면 app:layout_constraintTop_toBottomOf="@+id+cstLyMid"는 뭘까요?

=> 네 바로 constraint탑을 바텀에 맞춘다. 어디에? cstLyMid가 되는 겁니다. 

이거만 알아간다면 구조를 잡는데에 전혀 어려움이 없으실 겁니다 !

나머지는 여러분들이 한 번 해보시면 쉽게 접근 하실 수 있으실 겁니다 ! 

 

이제 엥? layout_width값과 height 값이 왜 0dp이지?? 라고 생각 하실 수 있습니다.

 

그 이유는 layout_width와 layout_height은 0dp,0dp로 해야 constraint값으로 매치가 됩니다 !

즉, 아까 설정한 app:layout_constraintTop_toBottomOf="@+id+cstLyMid와 등등 + percent의 비율에 따라 크기가 결정 된다는 소리입니다 !

 

Percent는 뭘까요??

cstLy의 속성 중 layout_constraintHeight_percent라는 attribute가 있습니다.

 

전체 cstLyMain의 높이는 1이구요 그의 child 자식 레이아웃들은 합쳐서 1이 되어야 합니다.

그래서  cstLyTop에 layout_constraintHeight_percent를 0.2를 주었구요.

cstLyMid에 0.3, cstLyBottom에 0.5를 주었습니다.

 

이렇게 1이 되었기 때문에 모든 휴대폰의 화면에 똑같은 비율로 출력돼 오류가 없는겁니다 박수!!

 

만약, 하나의 csyLy 안에 각종 위젯을 넣을 때 마찬가지로 cstLy를 추가해줘야합니다.

여기에 두개의 TextView가 있습니다. 정석은 이 cstLyMid안에 cstLy 2개를 추가해 다시 cstLyMid의 높이를 1로 생각해 맞춰줘야 하지만 전 미묘한 차이라 안했습니다. (귀찮은건 절대 아님..)

 layout_constraintWidth_percent도 1로 생각해서 화면의 비율에 맞게 출력되게 해야합니다!

 

FM으로 짠 cstLy를 보여드릴께요

버튼 5개 width값을 각 0.2씩 주고 하나씩 constraint를 만들었습니다. 아래 소스 첨부할께요!

자 이제 구조에 대해서는 어느정도 감이 잡히셨나요?

 

이상으로 constraintLayout 구조 잡기를 마치도록 하겠습니다. 

안드로이드 첫 포스팅인데, 아는만큼 표현하는게 쉽지는 않은 것 같네요 ㅠㅠ..

더 분발해서 돌아오겠습니다. 감사합니다 !

더보기

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cstLyFunction"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/logback">

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cstLyImage"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.7"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="1.0">

<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/imgDetail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="1.0"></com.github.chrisbanes.photoview.PhotoView>
</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cstLyBottom"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cstLyImage"
app:layout_constraintWidth_percent="1.0">

<TextView
android:id="@+id/txtTime"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:textColor="#A4A4A4"
android:textSize="14dp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cstLyBtn"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="1dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtTime"
app:layout_constraintWidth_percent="1.0">

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cstLyEmergency"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/cstLySiren"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.2">

<ImageButton
android:id="@+id/btnEmergency"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="20dp"
android:background="@drawable/ripple_unbounded"
android:src="@drawable/emercallicon"
android:text="비상연락"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="1" />

<TextView
android:id="@+id/txtEmergency"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="비상 연락"
android:textColor="#BDBDBD"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.23"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnEmergency"
app:layout_constraintWidth_percent="1" />
</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cstLySiren"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/cstLyPhoto"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintStart_toEndOf="@+id/cstLyEmergency"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.2">

<ImageButton
android:id="@+id/btnSiren"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="20dp"
android:background="@drawable/ripple_unbounded"
android:src="@drawable/sirenicon"
android:text="경보음"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="1" />

<TextView
android:id="@+id/txtSiren"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="경보음"
android:textColor="#BDBDBD"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.23"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnSiren"
app:layout_constraintWidth_percent="1" />
</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cstLyPhoto"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/cstLyConfirm"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintStart_toEndOf="@+id/cstLySiren"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.2">

<ImageButton
android:id="@+id/btnShowImage"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/ripple_unbounded"
android:src="@drawable/bigimageicon"
android:text="더보기"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="1" />

<TextView
android:id="@+id/txtShowImage"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="더보기"
android:textColor="#BDBDBD"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.23"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnShowImage"
app:layout_constraintWidth_percent="1" />
</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cstLyConfirm"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/cstLyLock"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintStart_toEndOf="@+id/cstLyPhoto"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.2">

<ImageButton
android:id="@+id/btnConfirm"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/ripple_unbounded"
android:src="@drawable/dooricon"
android:text="현관 확인"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="1" />

<TextView
android:id="@+id/txtConfirm"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="현관 확인"
android:textColor="#BDBDBD"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.23"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnConfirm"
app:layout_constraintWidth_percent="1" />
</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cstLyLock"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintStart_toEndOf="@+id/cstLyConfirm"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.2">

<ImageButton
android:id="@+id/btnLock"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/ripple_unbounded"
android:src="@drawable/lockicon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="1" />

<TextView
android:id="@+id/txtLock"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="비상 잠금"
android:textColor="#BDBDBD"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.23"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnLock"
app:layout_constraintWidth_percent="1" />

</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

ps.. 제가 이해를 잘못했거나 잘못 적힌 부분이 있으면 알려주시면 감사하겠습니다.

 

 

반응형