안드로이드 운영체제에서 멀티윈도우(Multi-Window) 기능은 사용자가 두 개 이상의 애플리케이션을 동시에 실행하며 작업을 병행할 수 있게 해줍니다. 그러나 특정 콘텐츠 재생이나 몰입형 경험을 제공하는 애플리케이션의 경우, 분할 화면 상태에서 상태 표시줄(Status Bar) 이 노출되면 사용자 경험(UX) 이 저하될 수 있습니다. 이에 따라 개발자는 활성 윈도우 내에서 시스템 바를 의도적으로 가려야 할 필요가 생깁니다.
1. 매니페스트 및 테마 정의 최적화
기본적인 구성 요소로는 AndroidManifest.xml 파일을 수정하여 해당 액티비티가 사용하는 테마를 명시하는 것이 우선입니다. 단순한 속성 추가보다는 커스텀 스타일을 활용하는 것이 유지보수에 유리합니다.
<application>
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/CustomImmersiveStyle">
</activity>
</application>
또한 리소스 디렉토리 내에 styles.xml 을 정의하여 액션바로 인한 간섭을 사전에 차단합니다.
<style name="CustomImmersiveStyle" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
주석 설명:
android:configChanges: 화면 회전이나 키보드 변경 시 액티비티 재시작을 방지하여 UI 일관성을 유지합니다.NoActionBar: 앱 상단의 네이티브 타이틀바를 제거하여 공간을 확보합니다.windowTranslucentStatus: 상태 영역에 투명도를 적용하여 레이아웃의 흐름을 자연스럽게 만듭니다.
2. 액티비티 내부의 UI 플래그 제어
코드 수준에서는 DecorView 의 시스템 UI 가시성 플래그를 조작하여 강제 숨김을 수행해야 합니다. 최근 안드로이드 버전에서는 SYSTEM_UI_FLAG_IMMERSIVE_STICKY 를 사용하여 사용자의 일시적인 터치에도 즉시 노출되지 않는 상태를 유지하는 것이 권장됩니다. Kotlin 언어로 작성된 예시 코드를 통해 구조를 변경하였습니다.
class MainActivity : AppCompatActivity() {
private lateinit var systemUiController: View
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
applyFullScreenLayout(R.layout.activity_main)
}
private fun applyFullScreenLayout(layoutId: Int) {
setContentView(layoutId)
systemUiController = findViewById<View>(android.R.id.content)
enableImmersiveMode()
}
private fun enableImmersiveMode() {
val uiOptions = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN)
systemUiController.systemUiVisibility = uiOptions
}
기술적 상세:
applyFullScreenLayout: 뷰 설정과 UI 초기화를 별도의 메서드로 분리하여 읽기 쉬운 구조를 만듭니다.SYSTEM_UI_FLAG_FULLSCREEN: 상태바 영역을 덮어씁니다.SYSTEM_UI_FLAG_HIDE_NAVIGATION: 하단 네이게이션 바를 함께 숨깁니다.
3. 윈도우 포커스 변화 감지 및 대응
분할 화면 환경에서는 다른 앱으로 전환되거나 윈도우 크기가 조절될 때 UI 가 복원되는 현상이 발생할 수 있습니다. 이를 방지하기 위해 onWindowFocusChanged 콜백을 오버라이드하여 포커스가 획득될 때마다 다시 플래그를 갱신하는 로직을 삽입합니다.
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
resetImmersiveState()
}
}
private fun resetImmersiveState() {
systemUiController.systemUiVisibility = (
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
)
}
핵심 포인트:
resetImmersiveState: 액티비티가 다시 활성화되었을 때 시스템 UI 설정을 강제로 재발행합니다.LAYOUT_FULLSCREEN: 내용을 상태바 영역까지 확장되도록 배치하도록 지시합니다.