컨스트레인트레이아웃 - Visibility 처리 (ConstraintLayout - Visibility Behavior)
1. 뷰의 Visibility.
안드로이드에서 뷰(View)의 Visibility는 크게 세 가지 중 하나의 상태를 가집니다.
- VISIBLE.
- INVISIBLE.
- GONE.
VISIBLE 상태는 말 그대로 뷰가 화면에 보이는 상태를 의미합니다. 레이아웃 내에서 뷰가 차지한 영역에 뷰의 컨텐츠가 그려져, 화면에 표시되고 있는 상태를 말하는 것이죠. 반면 INVISIBLE과 GONE은 둘 다 뷰가 화면에 표시되지 않은 상태를 의미합니다. 하지만 뷰가 화면에 표시되지 않는다고 해서 두 상태가 동일한 것은 아니고, 실제 영역을 차지하는지 여부에 따라 INVISIBLE과 GONE이 구분됩니다.
INVISIBLE은, 뷰 자신의 위치와 크기는 그대로 유지하지만, 뷰가 화면에 표시되지 않고 있는 상태를 말합니다. 쉽게 말해, 뷰가 "투명" 상태가 된 것이죠. 반면 GONE은, 화면에도 표시되지 않고 레이아웃 내에서 어떠한 영역도 차지하지 않는 상태를 의미합니다. 뷰가 "사라졌다(GONE)"고 생각하면 되겠죠?
그런데, 여기서 갑자기 뷰의 Visibility에 대한 얘기는 왜 꺼냈을까요? 이유는 바로, 뷰의 Visibility가 변경되었을 때, 컨스트레인트레이아웃이 어떻게 그것을 어떻게 다루는가에 대해 알아둘 필요가 있기 때문입니다.
특히, 제약(Constraint) 대상 뷰의 Visibility가 GONE 상태로 바뀌게 되는 경우에 말이죠.
2. 제약(Constraint) 대상 뷰가 GONE으로 변경.
자, 아래와 같이 두 개의 뷰가 일렬로 배치된 상황을 보죠. A는 부모의 왼쪽 사이드에 맞추고, B의 왼쪽은 A의 오른쪽 사이드에 맞췄습니다.
이 상황에서, A의 Visibility가 GONE 상태로 변경되면, 레이아웃 안에서 B가 차지하게 될 영역은 어떻게 될까요?
- A의 Visibility에 영향을 받지 않고 B의 영역을 그대로 유지한다.
- B의 왼쪽 사이드 제약 대상이었던 A가 없어졌으므로 A가 차지하던 영역만큼 늘어난다.
- A가 차지하고 있던 영역 크기만큼 B의 위치가 이동된다.
정답은 3번, "A가 차지하고 있던 영역 크기만큼 B의 위치가 이동된다." 입니다.
3. GONE 상태 처리.
레이아웃에서 GONE 상태로 변경된 뷰는, 레이아웃 배치에 있어서 크기가 0(zero)인 것으로 간주됩니다. 이 말은, 레이아웃 내에서 뷰의 존재 자체가 사라진 것은 아니라는 말이죠. 그러므로 위의 예제에서 B의 왼쪽 사이드 제약은 여전히 유효한, 하지만 크기가 0으로 간주된 A를 대상으로 적용되는 것입니다.
이렇게 컨스트레인트레이아웃에서 GONE 상태인 뷰를 처리하는 방식은, 레이아웃의 흐트러짐 없이 유연하고 일관되게 화면을 구성하게 만들어 줍니다.
그런데 어떤 경우에는 이런 상황을 만들고 싶지 않은 경우가 있겠죠? 레이아웃의 재배치를 하지 않고, 단순히 특정 뷰를 화면에서 보이지 않게만 만들고 싶은 경우.
네. 뷰를 INVISIBLE 상태로 만들면 됩니다.
4. INVISIBLE 상태 처리.
당연하게도 뷰를 INVISIBLE로 만들면 레이아웃의 뷰 위치를 조절하지 않고 해당 뷰만 표시하지 않게 만들 수 있습니다. INVISIBLE은 "뷰 자신의 위치와 크기는 그대로 유지"하기 때문이죠.
<?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:visibility="invisible" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEXT2"
android:textSize="60sp"
android:background="#FF0000"
app:layout_constraintLeft_toRightOf="@id/text1"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
5. 뷰가 GONE 상태가 되었을 때의 여백(Margin).
뷰의 상태가 GONE으로 되었을 때의 여백(Margin)에 대한 내용은 [컨스트레인트레이아웃 - 여백. (ConstraintLayout - Margins) - 3. 화면에 보이지 않는(GONE) 대상에 대한 여백(Margin).]에서 확인할 수 있습니다.
6. 참고.
- 개발자 레시피 - 컨스트레인트레이아웃 관련 항목
- [안드로이드 컨스트레인트레이아웃 (Android ConstraintLayout)]을 참고하세요.
- [컨스트레인트레이아웃 - 레이아웃 공통사항 (ConstraintLayout - Layout Common)]을 참고하세요.
- [컨스트레인트레이아웃 - 상대 위치 지정 (ConstraintLayout - Relative Positioning)]을 참고하세요.
- [컨스트레인트레이아웃 - 여백 (ConstraintLayout - Margins)]을 참고하세요.
- [컨스트레인트레이아웃 - 가운데 위치 지정과 Bias (ConstraintLayout - Centering Positioning and Bias)]을 참고하세요.
- [컨스트레인트레이아웃 - 원형 위치 지정 (ConstraintLayout - Circular Positioning)]을 참고하세요.
- 개발자 레시피 - 레이아웃 관련 항목
- [안드로이드 레이아웃 (Android Layout)]을 참고하세요.
- [안드로이드 레이아웃 공통사항 (Android Layout Common)]을 참고하세요.
- [안드로이드 리니어레이아웃 (Android LinearLayout)]을 참고하세요.
- [안드로이드 렐러티브레이아웃 (Android RelativeLayout)]을 참고하세요.
- 레이아웃에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 레이아웃 항목]을 참고하세요.
- ConstraintLayout에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 ConstraintLayout]을 참고하세요.
- [안드로이드 개발 참조문서 ConstraintLayout.LayoutParams]을 참고하세요.
- Build a Responsive UI with ConstraintLayout.
- [Build a Responsive UI with ConstraintLayout ]을 참고하세요.
.END.