Android 멀티윈도우 환경의 상태바 숨기기 전략

안드로이드 운영체제에서 멀티윈도우(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: 내용을 상태바 영역까지 확장되도록 배치하도록 지시합니다.

태그: Android MultiWindow StatusBar Kotlin AppUI

6월 9일 19:46에 게시됨