FrameLayout의 핵심 개념을 알아보세요 — Android SDK에서 가장 간단한 ViewGroup으로, 일반적으로 단일 자식 요소를 호스팅하거나 여러 요소를 서로 위에 오버레이하도록 설계되었습니다. FrameLayout은 플레이스홀더 컨테이너, 프래그먼트, 로딩 인디케이터 및 포어그라운드 요소에 편리합니다. 자식 배치를 관리하지 않으며, 각 후속 요소는 이전 요소 위에 그려지고 위치는 layout_gravity(left, top, right, bottom, center)에 의해 결정됩니다. 기본 시나리오는 FrameLayout API Reference에 설명되어 있습니다.
핵심 요점
FrameLayout은 Android SDK에서 가장 간단한 ViewGroup으로, 화면 영역을 차지하고 단일 자식 뷰(또는 여러 개의 오버레이)를 표시하도록 설계되었습니다. LinearLayout(순차 배치) 및 RelativeLayout(상대 위치)과 달리 FrameLayout은 자식 위치를 변경하지 않습니다. 각 새 자식은 기본적으로 왼쪽 상단 모서리(0,0)에 배치되고 이전 요소 위에 그려집니다.
FrameLayout은 API Level 1에서 도입되었으며 현재까지 가장 가벼운 Android 컨테이너입니다. 복잡한 로직으로 onMeasure를 재정의하지 않으며 최소한의 레이아웃 작업을 수행합니다. Android Performance Blog에 따르면 FrameLayout은 단일 패스로 onLayout을 실행하며 View를 직접 배치하는 것과 비교해 오버헤드가 거의 없습니다. 따라서 속도가 중요한 컨테이너(RecyclerView 항목 레이아웃, Fragment 컨테이너, 오버레이 레이어)에 이상적인 선택입니다.
FrameLayout의 크기는 기본적으로 가장 큰 자식 요소에 의해 결정됩니다(match_parent가 설정되지 않은 경우). 자식이 지정되지 않으면 FrameLayout은 (0,0)으로 축소됩니다. android:measureAllChildren 속성(아래 섹션)은 이 동작을 변경합니다.
FrameLayout은 ViewGroup을 상속하며 많은 특수 컨테이너의 직접적인 부모입니다: FragmentContainerView(프래그먼트), CardView(그림자 카드), ScrollView(단일 자식), NestedScrollView. Fragment 탐색으로 Activity를 생성할 때 표준 Android Studio 템플릿은 프래그먼트의 루트 컨테이너로 FrameLayout(또는 FragmentContainerView)을 사용합니다.
android:foreground — 모든 자식 요소 위에 그려지는 drawable을 지정하는 FrameLayout 속성입니다. background(자식 아래)와 달리 foreground는 콘텐츠 위에 표시되며 투명할 수 있습니다. 사용 용도: 누를 때 오버레이 효과(?attr/selectableItemBackground를 통한 리플), 이미지 마스킹, 상태 표시기 표시(이미지 위의 선택 확인 표시).
Foreground는 표준 drawable 리소스를 지원합니다: ColorDrawable, ShapeDrawable, RippleDrawable, LayerDrawable. API 23+부터 포어그라운드 위치 지정을 위해 android:foregroundGravity를 사용할 수 있습니다(fill, center, top, bottom). 채우기 모드에서 foreground는 전체 FrameLayout에 걸쳐 늘어납니다. 중앙 모드에서는 중앙에 그려집니다.
android:measureAllChildren — FrameLayout 크기를 계산할 때 모든 자식 요소를 측정할지 여부를 결정하는 부울 속성입니다(기본값 true). true(기본값)인 경우 FrameLayout은 GONE(크기 0)을 포함한 모든 자식의 크기를 고려합니다. false인 경우 FrameLayout은 VISIBLE 및 INVISIBLE 자식만 측정하며 GONE 요소는 계산에서 제외됩니다. Google I/O 2019에 따르면 GONE 요소가 많은 컨테이너(예: 가시성을 전환하는 목록)에서 measureAllChildren을 비활성화하면 초기 그리기가 20–60% 빨라집니다.
android:layout_gravity — FrameLayout(및 기타 ViewGroup)의 자식 요소 속성으로 컨테이너 내에서의 위치를 정의합니다. FrameLayout에서 layout_gravity는 자식 요소의 위치를 제어하는 유일한 방법입니다. FrameLayout은 자체 위치 지정 규칙(RelativeLayout과 같은)이나 방향(LinearLayout과 같은)을 제공하지 않기 때문입니다.
가능한 값: top, bottom, left, right, center, center_horizontal, center_vertical, fill, fill_horizontal, fill_vertical, clip_horizontal, clip_vertical. |를 통해 결합: android:layout_gravity="bottom|center_horizontal" — 요소가 아래쪽 가장자리에 고정되고 수평으로 중앙 정렬됩니다. FrameLayout보다 작은 요소의 경우 layout_gravity가 빈 공간에서의 위치를 결정합니다.
layout_gravity가 설정되지 않은 경우 요소는 기본적으로 왼쪽 상단 모서리(top|left)에 배치됩니다. 여러 자식을 포함하는 FrameLayout의 경우 각 자식은 고유한 layout_gravity를 가질 수 있습니다. 한 요소는 왼쪽 상단 모서리에, 다른 요소는 오른쪽 하단 모서리에, 세 번째 요소는 중앙에 있을 수 있습니다. 이를 통해 간단한 오버레이(예: 이미지 위의 닫기 아이콘)를 만들 수 있습니다.
android:gravity(부모 속성)는 FrameLayout 내부의 콘텐츠를 정렬합니다(예: TextView 내부의 텍스트). android:layout_gravity(자식 속성)는 요소 자체를 FrameLayout 내부에서 정렬합니다. FrameLayout의 맥락에서 gravity는 자식이 기본적으로 어떻게 배치되는지 정의합니다(모든 자식에 대해 한 번에 layout_gravity를 설정하는 것과 유사). 그러나 각 특정 요소의 layout_gravity는 부모 값을 재정의합니다.
오른쪽 하단 모서리에 텍스트 레이블이 있는 이미지. FrameLayout에는 화면을 채우는 ImageView와 이미지 위에 배치하기 위한 layout_gravity="bottom|end"의 TextView가 포함됩니다.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="200dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/product_photo"
android:scaleType="centerCrop" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="8dp"
android:background="@drawable/badge_background"
android:elevation="2dp"
android:paddingHorizontal="8dp"
android:paddingVertical="4dp"
android:text="-30%"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
</FrameLayout>
ImageView는 전체 FrameLayout(높이 200dp)을 채웁니다. layout_gravity="bottom|end"의 TextView는 이미지 위 오른쪽 하단 모서리에 배치됩니다. elevation=2dp는 레이블 아래에 그림자를 추가하여 이미지와 시각적으로 분리합니다. 이 최소한의 예제는 LinearLayout에서 중첩 컨테이너나 사용자 정의 코드가 필요했을 것입니다.
로딩 중에 나타나는 중앙 진행 표시줄이 있는 콘텐츠 화면. FrameLayout에는 콘텐츠와 visibility="gone"의 ProgressBar(코드에서 전환)의 두 요소가 포함됩니다.
<FrameLayout
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/content_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="로드된 콘텐츠"
android:textSize="18sp" />
<ProgressBar
android:id="@+id/loading_spinner"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
ProgressBar는 기본적으로 숨겨져 있습니다(gone). 로딩이 시작되면 findViewById(R.id.loading_spinner).visibility = View.VISIBLE이 호출되어 스피너가 콘텐츠 위 중앙에 나타납니다. 로딩 후에는 .visibility = View.GONE입니다. FrameLayout은 콘텐츠 위치를 이동하지 않고 오버레이를 제공합니다. ProgressBar가 위에 그려지므로 스피너가 나타나도 텍스트가 움직이지 않습니다.
FragmentTransaction의 표준 컨테이너로서의 FrameLayout. 액티비티는 탐색에 따라 이 컨테이너 내부의 프래그먼트를 교체합니다.
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
import androidx.fragment.app.FragmentTransaction
val fragmentContainer = R.id.fragment_container
fun navigateTo(fragment: Fragment) {
supportFragmentManager
.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(fragmentContainer, fragment)
.addToBackStack(null)
.commit()
}
프래그먼트 컨테이너로서의 FrameLayout은 Fragment Navigation을 지원하는 가장 가벼운 방법입니다. Navigation Component 2.4+에서는 FragmentContainerView(FrameLayout의 하위 클래스)가 권장되지만, 단순한 FrameLayout도 수동 FragmentTransaction에 유효합니다. 주요 장점은 FragmentTransaction.replace()가 액티비티에 영향을 주지 않고 콘텐츠를 완전히 교체한다는 것입니다.
FrameLayout은 네 가지 시나리오에 최적입니다: 프래그먼트 컨테이너(FragmentContainerView 또는 FrameLayout), 로딩 오버레이(콘텐츠 위의 ProgressBar), 카드 레이블(이미지 위의 레이블), ViewStub용 플레이스홀더 컨테이너(지연 로딩).
적합하지 않은 경우: 여러 요소의 복잡한 위치 지정(ConstraintLayout 사용), 순차 목록(LinearLayout 또는 RecyclerView), 요소 순서가 변경되는 동적 레이아웃.
화면의 루트 요소로서의 FrameLayout — 화면에 2~3개 이상의 요소가 있는 경우 나쁜 방법입니다. 루트 컨테이너에는 ConstraintLayout을 사용하세요. 성능 저하 없이 위치 지정에 대한 더 많은 제어를 제공합니다. 오버레이나 플레이스홀더가 필요한 자식 블록에만 FrameLayout을 사용하세요.
자주 묻는 질문
FrameLayout — 위치 지정 시스템이 없는 미니멀한 컨테이너(layout_gravity만 있음), 요소 오버레이용으로 설계되었습니다. ConstraintLayout — 제약 조건, 체인, 배리어, 백분율 치수 및 MotionLayout 지원을 갖춘 본격적인 레이아웃 시스템입니다. FrameLayout은 단순한 경우(자식 1개 또는 오버레이)에 더 빠릅니다. 복잡한 레이아웃에는 ConstraintLayout이 필요합니다. 선택: 로딩 오버레이와 프래그먼트 컨테이너에는 FrameLayout, 그 외에는 ConstraintLayout을 사용하세요.
원하는 축에서 FrameLayout 크기를 wrap_content로 설정하세요(android:layout_width="wrap_content" 및/또는 android:layout_height="wrap_content"). 그러면 FrameLayout이 가장 큰 자식 요소의 크기에 맞게 조정됩니다. 모든 자식이 FrameLayout보다 작으면 여분의 공간이 비어 있습니다. 정확한 제어를 위해 고정 padding과 함께 match_parent를 사용하세요.
이는 FrameLayout의 의도된 동작입니다 — 공간에 자식을 분산시키지 않고 순차적으로 서로 위에 그립니다. 요소가 겹치지 않도록 하려면 다른 컨테이너(LinearLayout, ConstraintLayout)를 사용하세요. 그리기 순서를 제어하면서 부분적으로 겹치게 하려면 오프셋에 layout_gravity를, Z-순서에 elevation을 사용하세요.
FrameLayout이 더 빠릅니다 가장 단순한 경우(자식 요소 1개, 복잡한 위치 지정 없음)에 대해. FrameLayout은 제약 조건을 계산하지 않고 최소 시간에 onMeasure를 수행합니다. 그러나 차이는 수백 번의 반복(수만 개의 항목이 있는 RecyclerView)에서만 눈에 띕니다. 일반적인 화면(1~3개의 FrameLayout)에서는 차이가 마이크로초 수준으로 UX에 영향을 미치지 않습니다. ConstraintLayout은 95%의 작업에 보편적인 선택입니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.