안드로이드 프레임레이아웃. (Android FrameLayout)
1. 안드로이드 FrameLayout
[안드로이드 리니어레이아웃 (Android LinearLayout)]과 [안드로이드 렐러티브레이아웃 (Android RelativeLayout)]에서 봤듯이 Layout 클래스는 자신만의 배치 기능에 따라, Layout에 포함된 다양한 뷰(View) 위젯을 화면에 정렬할 때 사용합니다. 그런데 화면에 뷰(View) 위젯을 표시함에 있어 주 목적이 다른 Layout 클래스가 하나 있습니다. 바로 FrameLayout
입니다.
FrameLayout
은 자식(Children)으로 추가된 여러 뷰(View) 위젯들 중 하나를 Layout의 전면에 표시할 때 사용하는 클래스입니다. "Frame"이라는 단어의 의미가 "액자"라는 것을 떠올려보면, FrameLayout
의 동작 방식을 좀 더 쉽게 이해할 수 있죠.
보통 "액자(Frame)"에는 사진을 끼워서 사용합니다. 그리고 분위기(?) 또는 취향(?)에 따라 "액자(Frame)"에 있는 사진을 빼고, 다른 사진을 끼워서 사용하죠. FrameLayout
의 주 용도는, 바로 이 "액자(Frame)"처럼, 화면에 표시될 뷰(View)를 바꿔가면서 표시하기 위함입니다.
그런데 FrameLayout
이 하나의 자식(Child) 뷰 위젯을 전면에 표시할 때 사용된다고 해도, 오직 하나의 자식(Child) 뷰 위젯만 가질 수 있다거나, 전면에 표시되는 뷰(View) 외의 다른 뷰(View)가 아예 표시조차 되지 않는 것은 아닙니다. 보통 "액자(Frame)"에도 액자 크기만한 큰 사진 앞에 작은 사진들을 끼워서 사용하는 경우가 있죠. 마찬가지로 FrameLayout
에도 다양한 크기의 뷰(View) 위젯들을 추가할 수 있습니다.
최초 FrameLayout
이 화면에 그려질 때 전면에 표시되는 뷰(View) 위젯은 레이아웃 XML 코드의 가장 마지막에 추가된 뷰(View) 위젯입니다. 즉, "액자(Frame)"에 그림을 끼우면 젤 앞에 끼워진 그림이 전면에 보여지듯이, FrameLayout
에 가장 마지막으로 추가된 자식(Children) 뷰 위젯이 화면의 전면에 표시되는 것이죠. 그리고 FrameLayout
에 추가되는 자식(Children)들은 뒤에서부터 앞으로 쌓이면서 그려지기 때문에, 전면에 표시되는 뷰(View)의 크기가 다른 뷰(View)보다 작으면, 먼저 추가된 뷰(View)의 일부가 화면에 보여지게 됩니다.
하지만 안드로이드에서는, 여러 뷰(View)를 동시에 표시해야 하는 명확한 의도가 없는 한, FrameLayout
이 오직 하나의 자식(Child) 뷰 위젯만을 표시하게 만들도록 권고하고 있습니다. 자식(Children) 뷰들이 서로 겹치지 않으면서, 다양한 화면 크기에 따라 스케일될 수 있는(scalable) UI를 구성하기가 어렵기 때문입니다.
그리고 FrameLayout
의 layout_width와 layout_height 값이 "wrap_content"인 경우, FrameLayout
의 크기는, 자신에게 포함된 자식(Children) 뷰 위젯 중에서 가장 큰 뷰(View) 위젯에 맞춰집니다.
2. FrameLayout 사용 방법
2.1 FrameLayout 기본 사용법
FrameLayout
에 자식(Children) 뷰 위젯을 표시하는 방법은 간단합니다. "<FrameLayout>"과 "</FrameLayout>"사이에 뷰(View) 위젯을 선언하면 됩니다.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:background="#4CAF50"
android:id="@+id/text1"
android:text="TEXT1" />
</FrameLayout>
앞서 잠시 언급한대로, FrameLayout
에 여러 개의 자식(Children)을 추가하면, 기본적으로 가장 마지막에 추가된 뷰(View)가 가장 전면에 표시됩니다.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="48sp"
android:background="#4CAF50"
android:id="@+id/text1"
android:text="TEXT1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="36sp"
android:background="#FF9800"
android:id="@+id/text2"
android:text="TEXT2" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:background="#009688"
android:id="@+id/text3"
android:text="TEXT3" />
</FrameLayout>
2.2 FrameLayout 내 자식(Children) 뷰 위젯의 위치 조절.
앞선 예제에서 봤듯이, FrameLayout
에 추가된 뷰(View) 위젯은 기본적으로 FrameLayout
의 왼쪽(Left), 위(Top)를 기준으로 정렬됩니다. 그런데 이러한 정렬 기준은 FrameLayout
의 각 자식(Children) 뷰 위젯에 "layout_gravity" 속성 값을 지정하여 변경할 수 있습니다.
* android:layout_gravity - 자신이 속한 부모 Layout내 자신의 정렬 위치 값 지정.
> 부모 Layout 내에서 x축(좌/우)과 y축(상/하)을 기준으로 정렬.
> 아래 값들 중에서 하나 이상의 값을 '|' 기호로 혼합하여 사용.
-. top (0x30) : 부모 Layout 안에서, 위쪽에 위치.
-. bottom (0x50) : 부모 Layout 안에서, 아래쪽에 위치.
-. left (0x03) : 부모 Layout 안에서, 왼쪽에 위치.
-. right (0x05) : 부모 Layout 안에서, 오른쪽에 위치.
-. center_vertical (0x10) : 세로 기준으로 가운데 위치.
-. fill_vertical (0x70) : 세로 방향으로 가득 채움.
-. center_horizontal (0x01) : 가로 기준으로 가운데 위치.
-. fill_horizontal (0x07) : 가로 방향으로 가득 채움.
-. center (0x11) : 가로, 세로 기준으로 가운데 정렬.
-. fill (0x77) : 가로, 세로 방향으로 가득 채움.
-. clip_vertical (0x80) : 세로 기준으로 Layout을 넘어서는 영역 자르기.
-. clip_horizontal (0x08) : 가로 기준으로 Layout를 넘어서는 영역 자르기.
-. start (0x00800003) : 부모 Layout 안에서, 시작 위치에 정렬.
-. end (0x00800005) : 부모 Layout 안에서, 끝 위치에 정렬.
> 기본 정렬은 가로 방향 start, 세로 방향 top.
각 속성 값에 따른 표시 내용은 아래와 같습니다.
참고로, 현재 fill 관련 속성 값(fill_hotizontal, fill_vertical, fill) 및 clip 관련 속성 값(clip_horizontal, clip_vertical)은 FrameLayout
에서 적용되지 않는 것으로 파악됩니다. (하지만, 추가적인 내용이 파악되면 내용을 보충하여 본문에 기록하겠습니다.)
FrameLayout
에 포함된 자식(Children) 뷰 위젯에 각각 다른 gravity를 적용하여 FrameLayout
내 다른 영역에 표시되도록 만들 수 있습니다.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#4CAF50"
android:textSize="24sp"
android:layout_gravity="left|top"
android:text="TEXT 1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF9800"
android:textSize="24sp"
android:layout_gravity="center"
android:text="TEXT 2" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#009688"
android:textSize="24sp"
android:layout_gravity="right|bottom"
android:text="TEXT 3" />
</FrameLayout>
3. FrameLayout에 표시될 자식(Children) 뷰 변경하기
FrameLayout
에 표시될 뷰(View)를 변경하는 방법은 크게 두 가지가 있습니다. FrameLayout
이 무조건 하나의 자식(Child) 뷰 위젯만 가지도록 만드는 방법과 FrameLayout
에 포함된 자식(Children) 뷰 위젯들의 보이기(visibility) 속성을 사용하여, 오직 하나의 뷰(View)만 화면에 표시되도록 만드는 것입니다.
3.1 FrameLayout에 뷰 추가(addView()) 또는 뷰 삭제(removeView()).
FrameLayout
에 표시될 뷰(View)를 결정하는 가장 직관적인 방법은, FrameLayout
이 오직 하나의 자식(Child) 뷰만 가지도록 만드는 것입니다. 만약 다른 뷰(View)가 표시되어야 한다면, 기존 뷰(View)는 없애고 새로운 뷰(View)를 추가하는 것이죠. 마치 "액자(Frame)"의 사진을 바꿔 끼우듯이 말이죠.
이는 FrameLayout
의 addView() 함수와 removeView() 또는 removeViewAt() 함수를 사용하여 수행할 수 있습니다.
아래는 addView()와 removeViewAt() 함수를 사용하여 FrameLayout
에 표시될 자식(Child) 뷰 위젯을 변경하는 예제입니다.
private void changeView(int index) {
frame.removeViewAt(0) ;
switch (index) {
case 0 :
frame.addView(textView1) ;
break ;
case 1 :
frame.addView(textView2) ;
break ;
case 2 :
frame.addView(textView3) ;
break ;
}
}
3.2 FrameLayout에 추가된 자식(Children) 뷰의 보이기(Visibility) 속성 사용.
두 번째 방법은 미리 FrameLayout
에 여러 자식(Children) 뷰 위젯들을 추가해두고, 자식(Children) 뷰 위젯의 visibility 속성을 사용하여 화면에 표시될 뷰(View)를 변경하는 방법입니다.
레이아웃 XML 코드를 작성할 때, 최초 화면에 표시될 뷰(View)만 visibility 속성 값을 "visible"로 지정하고, 나머지 뷰(View)는 "invisible"로 지정합니다.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frame">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/text1"
android:visibility="visible"
android:text="TEXT 1" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/text2"
android:visibility="invisible"
android:text="TEXT 2" />
</FrameLayout>
자바 코드에서는, 뷰(View)의 참조를 가져온 다음, 뷰(View)의 setVisibility() 함수를 사용하여 화면 표시 여부를 결정할 수 있습니다.
private void changeView(int index) {
TextView textView1 = (TextView) findViewById(R.id.text1) ;
TextView textView2 = (TextView) findViewById(R.id.text2) ;
switch (index) {
case 0 :
textView1.setVisibility(View.VISIBLE) ;
textView2.setVisibility(View.INVISIBLE) ;
break ;
case 1 :
textView1.setVisibility(View.INVISIBLE) ;
textView2.setVisibility(View.VISIBLE) ;
break ;
}
}
4. FrameLayout이 사용되는 UI
앞서 FrameLayout
이 오직 하나의 자식(Child) 뷰 위젯만을 표시하는데 사용된다고 설명했습니다. 그러므로 안드로이드 SDK에서 FrameLayout
이 사용되는 곳을 보면, 하나의 Layout 영역에 여러 종류의 뷰(View)를 번갈아가며 표시하는데 사용되는 것을 확인할 수 있습니다.
4.1 Fragment의 컨테이너로써의 FrameLayout
Fragment
는 화면을 여러 모듈 단위로 구성할 수 있도록 만들어주는 기능입니다. 특히, 화면 크기에 따라 동적 변화가 필요한 UI를 구성하기에 적합한 요소인데요, 이 Fragment
가 표시되는 컨테이너(Container)로써 FrameLayout
이 주로 사용됩니다.
Fragment
에 대한 자세한 설명은 [안드로이드 프래그먼트 기본 사용법 (Android Fragment)]을 참고하시기 바랍니다.
4.2 탭 호스트(TabHost)의 내용(Content)을 위한 페이지를 표시하는 FrameLayout
탭 호스트(TabHost)는 여러 페이지로 구성된 화면을 동일한 영역에 번갈아 표시할 때 사용되는 UI 구성요소입니다. 탭 호스트(TabHost)는 탭(Tab) 버튼을 포함하는 탭 위젯(TabWidget)과, 버튼 선택에 따라 그 내용을 표시하는 페이지로 구성되는데요. 바로 이 "페이지가 표시되는 영역"에 FrameLayout
이 사용됩니다.
안드로이드 탭(Android Tab)에 대한 자세한 설명은 [안드로이드 탭 기본 사용법]에서 확인할 수 있습니다.
5. 참고.
- 개발자 레시피 - 레이아웃 관련 항목
- [안드로이드 레이아웃 (Android Layout)]을 참고하세요.
- [안드로이드 레이아웃 공통사항 (Android Layout Common)]을 참고하세요.
- [ 안드로이드 리니어레이아웃 (Android LinearLayout)]을 참고하세요.
- [안드로이드 렐러티브레이아웃 (Android RelativeLayout)]을 참고하세요.
- 레이아웃에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 레이아웃 항목]을 참고하세요.
- FrameLayout에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 FrameLayout]을 참고하세요.
.END.