컨스트레인트레이아웃 - 여백. (ConstraintLayout - Margins)

2019. 4. 24. 15:21


1. 컨스트레인트레이아웃 뷰 위젯 여백(Margin).

이전 글, [안드로이드 레이아웃 공통사항 (Android Layout Common) - 4. 컨스트레인트레이아웃 뷰 위젯 간 여백]에서 컨스트레인트레이아웃의 여백(Margin)에 대해 간략하게 설명했었는데요, 여기서 조금 더 깊은 내용을 알아보겠습니다.

ConstraintLayout Margins


2. 뷰 위젯 여백 적용

컨스트레인트레이아웃에 포함된 뷰 위젯의 여백을 지정하는 방법은 기본적으로 다른 레이아웃에서 여백을 설정하는 방법과 동일합니다. 아래의 속성을 사용하여 뷰 위젯간 여백을 지정할 수 있습니다.


여백(Margin) 관련 속성 설명
layout_marginStart 뷰 위젯의 시작(Start) 사이드 여백 설정.
layout_marginEnd 뷰 위젯의 끝(Start) 사이드 여백 설정.
layout_marginLeft 뷰 위젯의 왼쪽(Left) 사이드 여백 설정.
layout_marginTop 뷰 위젯의 위(Top) 사이드 여백 설정.
layout_marginRight 뷰 위젯의 오른쪽(Right) 사이드 여백 설정.
layout_marginBottom 뷰 위젯의 아래(Bottom) 사이드 여백 설정.


ConstraintLayout Margin 관련 속성


하지만 컨스트레인트레이아웃에서는, 자식 뷰 위젯에 여백 관련 속성을 사용한다고 해서 무조건적으로 적용되는 것은 아닙니다. 여백과 관련된 속성이 적용되려면, 속성이 적용된 사이드(Side)에 해당하는 제약(Constraint)이 명시적으로 지정되어 있어야 합니다. 즉, 컨스트레인트레이아웃의 자식 뷰 위젯의 사이드에 여백을 지정하려면, 해당 사이드에 상대 위치 지정(Relative Positioning) 제약이 적용되어야 하며, 만약 아무런 제약도 지정되지 않고 여백만 사용하게 되면 그 여백 설정은 무시됩니다.


아래의 예제는 제약(Constraint)이 적용되지 않았을 때와 제약(Constraint)이 적용되었을 때의 여백 관련 속성이 적용되는 차이를 보여주는 예제입니다.


첫 번째 텍스트뷰의 경우 "layout_marginLeft" 속성과 "layout_marginTop" 속성이 사용되었으나, 왼쪽(Left), 위(Top) 사이드에 어떠한 제약도 지정되지 않았기 때문에 어떠한 여백도 표시되지 않은 것을 확인할 수 있습니다. 그리고 두 번째 텍스트뷰에는 "layout_marginLeft", "layout_marginTop" 속성에 더하여 "layout_constraintLeft_toRightOf", "layout_constraintTop_toTopOf" 속성을 통해 각각 왼쪽(Left), 위(Top) 사이드 제약을 지정하였으므로 "30dp"만큼의 여백이 표시된 것을 확인할 수 있습니다.


부모 레이아웃 기준 제약(Constraint) 지정에 따른 여백(Margin) 표시 여부.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/text1"
        android:text="TEXT1"
        android:textSize="60sp"
        android:background="#00FF00"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="30dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TEXT2"
        android:textSize="60sp"
        android:background="#FF0000"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="30dp"
        app:layout_constraintLeft_toRightOf="@id/text1"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

부모 레이아웃 기준 제약(Constraint) 지정에 따른 여백(Margin) 표시 여부.


3. 화면에 보이지 않는(GONE) 대상에 대한 여백(Margin).

컨스트레인트레이아웃은 뷰 위젯 간 여백 설정 시 사용하는 레이아웃 공통 여백 속성 외에, 대상 뷰가 화면에서 보이지 않는 상태(View.GONE)가 되었을 때 지정할 수 있는 별도의 여백 관련 속성을 제공합니다.


  * layout_goneMarginLeft - 뷰 위젯의 왼쪽(Left) 사이드 대상 뷰가 View.GONE 상태일 때 여백 설정.
        > 치수 단위 값 사용. (sp, px, dp, in, mm 단위 사용 가능)

  * layout_goneMarginTop - 뷰 위젯의 위(Top) 사이드 대상 뷰가 View.GONE 상태일 때 여백 설정.
        > 치수 단위 값 사용. (sp, px, dp, in, mm 단위 사용 가능)

  * layout_goneMarginRight - 뷰 위젯의 오른쪽(Right) 사이드 대상 뷰가 View.GONE 상태일 때 여백 설정.
        > 치수 단위 값 사용. (sp, px, dp, in, mm 단위 사용 가능)

  * layout_goneMarginBottom - 뷰 위젯의 아래(Bottom) 사이드 대상 뷰가 View.GONE 상태일 때 여백 설정.
        > 치수 단위 값 사용. (sp, px, dp, in, mm 단위 사용 가능)

  * layout_goneMarginStart - 뷰 위젯의 시작(Start) 사이드 대상 뷰가 View.GONE 상태일 때 여백 설정.
        > 치수 단위 값 사용. (sp, px, dp, in, mm 단위 사용 가능)

  * layout_goneMarginEnd - 뷰 위젯의 끝(Start) 사이드 대상 뷰가 View.GONE 상태일 때 여백 설정.
        > 치수 단위 값 사용. (sp, px, dp, in, mm 단위 사용 가능)

그런데 View.GONE 상태에 대한 여백(Margin) 속성이 별도로 존재하는 이유는 무엇일까요? 어떤 경우에 "layout_goneMarginXXX" 속성을 사용하는 걸까요?


자, 아래 그림과 같이, 텍스트뷰(또는 버튼) 여러 개가 나열된 상황을 가정해 봅시다.


layout_goneMarginXXX 예제 화면 1


일반적인 상황에서, 모든 텍스트뷰가 화면에 표시되었을 때는 첫 번째 텍스트뷰의 왼쪽에 30dp 여백이, 그 뒤에 추가되는 텍스트뷰는 10dp의 여백을 가지게 만들었습니다.

layout_goneMarginXXX 예제 화면 2


그런데 어떠한 조건에 의해 첫 번째 텍스트뷰가 화면에 표시되지 않아야 할 상황이 된다면, TEXT1을 View.GONE 상태로 만들어야 하고, 그에 따른 결과 화면은 아래와 같이 표시될 것입니다.

layout_goneMarginXXX 예제 화면 3


자, 어떤가요? 첫 번째 화면에서 TEXT1만 가려진 결과가 표시되었나요? 음, 그런데 조금 이상하네요. TEXT2가 앞으로 당겨지면서 원래 TEXT1이 가졌던 30dp의 여백이 무효화되고 TEXT2에 지정되어 있던 10dp의 여백이 그대로 적용되어 버렸습니다. 이로 인해 표시되길 기대했던 화면에서 조금 어긋나버렸네요. 어떻게 하죠?

layout_goneMarginXXX 예제 화면 4


네. 예상하신대로, 이런 경우를 위해, "layout_goneMarginXXX" 속성을 사용하여 대상이 View.GONE 상태일 때의 여백을 따로 설정할 수 있게 만들어놓은 것입니다. 아래 그림처럼 말이죠.

layout_goneMarginXXX 예제 화면 5


4. 참고.

.END.


ANDROID 프로그래밍/LAYOUT