Java프로그래밍

[Android] 휴대폰 하단 시스템 네비게이션 바(뒤로가기, 홈, 최근 앱 버튼이 있는 바)를 숨기는 방법

앱 하단의 시스템 네비게이션 바를 숨기고 전체 화면(몰입 모드, Immersive Mode)으로 만들려면, 액티비티의 Window 객체를 통해 시스템 UI 관련 플래그를 설정해야 한다.

앱의 Activity (예: MainActivity.java 또는 앱 전체에 적용하려면 BaseActivity)의 onCreate 또는 onResume 메소드, 혹은 사용자가 특정 버튼을 눌렀을 때 등 원하는 시점에 아래 코드를 추가하여 시스템 UI를 숨길 수 있다.




최신 방식 (Android 11 이상 권장, 하위 호환 지원): WindowInsetsControllerCompat 사용

import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;

// Activity 내에서
private void hideSystemUI() {
    WindowCompat.setDecorFitsSystemWindows(getWindow(), false); // 앱 콘텐츠를 시스템 바 영역까지 확장
    WindowInsetsControllerCompat controller = WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());
    if (controller != null) {
        // 시스템 바 (상태 표시줄, 네비게이션 바) 숨기기
        controller.hide(WindowInsetsCompat.Type.systemBars());
        // 화면 가장자리를 스와이프해야 시스템 바가 잠시 나타나도록 설정
        controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
    }
}

// 시스템 UI를 다시 보이게 하려면
private void showSystemUI() {
    WindowCompat.setDecorFitsSystemWindows(getWindow(), true); // 앱 콘텐츠 영역 복원
    WindowInsetsControllerCompat controller = WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());
    if (controller != null) {
        // 시스템 바 다시 표시
        controller.show(WindowInsetsCompat.Type.systemBars());
    }
}

// 예시: onCreate에서 호출
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // setContentView 이후 또는 전에 호출 가능
    hideSystemUI();
    // ...
}

// 예시: 화면 터치 시 UI 토글
// @Override
// public void onWindowFocusChanged(boolean hasFocus) {
//     super.onWindowFocusChanged(hasFocus);
//     if (hasFocus) {
//         hideSystemUI();
//     }
// }

getWindow()Activity 또는 Dialog 안에서만 정상적으로 쓸 수 있다.
Context만 있는 클래스에서는 getWindow() 사용할 수 없다.

import androidx.core.view.WindowCompat;

public class MyActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
    }
}


만약 현재 클래스가 Activity가 아니면?

  • Context만 가지고 있으면 getWindow()를 쓸 수 없다
  • Activity를 받아와야 한다.

예시 (Context → Activity 변환해서 사용하는 방법):

if (context instanceof Activity) {
    Activity activity = (Activity) context;
    WindowCompat.setDecorFitsSystemWindows(activity.getWindow(), false);
}



이전 방식 (Android 11 미만): System UI Visibility Flags 사용

import android.view.View;

// Activity 내에서
private void hideSystemUI_Legacy() {
    View decorView = getWindow().getDecorView();
    int uiOptions = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY // 스와이프 시 잠시 보임
                  | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                  | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                  | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                  | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // 네비게이션 바 숨기기
                  | View.SYSTEM_UI_FLAG_FULLSCREEN; // 상태 표시줄 숨기기
    decorView.setSystemUiVisibility(uiOptions);
}

// 시스템 UI를 다시 보이게 하려면
private void showSystemUI_Legacy() {
    View decorView = getWindow().getDecorView();
    int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                  | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                  | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    decorView.setSystemUiVisibility(uiOptions);
}

// 예시: onCreate에서 호출
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    hideSystemUI_Legacy();
    // ...
}

주의할점

하위 호환성: 최신 앱에서는 WindowInsetsControllerCompat 사용이 권장됨. 이 API는 내부적으로 이전 버전과의 호환성을 처리해 준다.

호출 시점:onCreate에서 호출하면 액티비티 시작 시부터 적용됨. 사용자가 특정 액션을 취했을 때 숨기거나 보이게 할 수도 있다.

테마: 앱의 테마가 .NoActionBar이면서 전체 화면 관련 속성(windowTranslucentNavigation 등)이 설정되어 있으면 동작에 영향을 줄 수 있다.

Fragment 내에서 호출

getWindow() 메소드는 Activity 클래스에 속해 있습니다. 만약 이 코드를 Fragment 안에서 사용하려고 하셨다면, 직접 getWindow()를 호출할 수 없기 때문에 빨간색으로 표시될 수 있다.


Fragment 내에서 시스템 UI를 제어해야 한다면, ActivityWindow 객체에 접근해야 한다. requireActivity().getWindow() 또는 getActivity().getWindow() (null 체크 필요)를 사용

// Fragment 클래스 내부
import android.view.Window;
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
// ...

private void hideSystemUIFromFragment() {
    // Fragment에서는 requireActivity() 또는 getActivity() 사용
    if (getActivity() != null) {
        Window window = requireActivity().getWindow(); // 또는 getActivity().getWindow()
        WindowCompat.setDecorFitsSystemWindows(window, false);
        WindowInsetsControllerCompat controller = WindowCompat.getInsetsController(window, window.getDecorView());
        if (controller != null) {
            controller.hide(WindowInsetsCompat.Type.systemBars());
            controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
        }
    }
}

 private void showSystemUIFromFragment() {
    if (getActivity() != null) {
        Window window = requireActivity().getWindow(); // 또는 getActivity().getWindow()
        WindowCompat.setDecorFitsSystemWindows(window, true);
        WindowInsetsControllerCompat controller = WindowCompat.getInsetsController(window, window.getDecorView());
        if (controller != null) {
            controller.show(WindowInsetsCompat.Type.systemBars());
        }
    }
}

error: Content is protected !!