Community코딩 & 개발github.com

wasay-rao/kmp-edge-to-edge

Compose Multiplatform에서 Android 및 iOS의 엣지 투 엣지 레이아웃 구현 - 플랫폼별 활성화, Scaffold와 WindowInsets, 리스트, 하단 바, 키보드(IME), 디스플레이 컷아웃, 시스템 바 아이콘 대비 및 화면 가장자리의 광고 배너를 지원합니다. 화면 스캐폴드를 구축하거나 상태 표시줄, 네비게이션 바, 노치 또는 키보드에 가려진 콘텐츠를 수정하거나 Android 15 이상을 대상으로 할 때 사용하세요.

kmp-edge-to-edge란 무엇인가요?

이 스킬은 Compose Multiplatform 애플리케이션에서 엣지 투 엣지(edge-to-edge) 레이아웃을 구현하는 방법을 안내합니다. Android 15(API 35)부터 강제화되며, iOS에서도 상태 표시줄 아래까지 콘텐츠를 그리는 것이 일반적인 요구사항입니다. 이 스킬은 Android의 `enableEdgeToEdge()` 호출과 iOS의 `ignoresSafeArea()` 설정을 통해 각 플랫폼에서 엣지 투 엣지를 활성화하는 방법을 설명하고, Scaffold가 대부분의 inset 처리를 자동으로 수행하는 방법을 보여줍니다. 또한 키보드(IME) 대응, 전체 화면 콘텐츠 처리, 시스템 바 아이콘 대비, 광고 배너 배치 등 실전에서 필요한 모든 주제를 다룹니다. 체크리스트를 통해 각 화면이 올바르게 동작하는지 확인할 수 있으며, Google의 edge-to-edge 스킬을 Android 관련 문제 해결에 활용할 것을 권장합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/wasey-rao/kmp-agent-studio/tree/HEAD/kmp-studio/skills/kmp-edge-to-edge

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Compose Multiplatform에서 엣지 투 엣지

Android는 SDK 35 이상을 대상으로 하는 앱에 엣지 투 엣지를 강제하며, 36에서는 옵트아웃이 사라집니다. iOS 앱은 상태 표시줄과 홈 인디케이터 아래에 콘텐츠를 그리는 것이 일반적입니다. 처음부터 모든 화면을 엣지 투 엣지로 구축하세요.

규칙: 배경은 시스템 바 뒤에 그려지고, 콘텐츠와 컨트롤은 인셋으로 패딩됩니다.

활성화하기

Android (androidApp의 MainActivity), setContent 전:

override fun onCreate(savedInstanceState: Bundle?) {
    enableEdgeToEdge()
    super.onCreate(savedInstanceState)
    setContent { App() }
}

매니페스트에서 액티비티에 android:windowSoftInputMode="adjustResize"를 설정하여 IME 인셋이 Compose에 도달하도록 합니다.

iOS (ContentView.swift): Compose가 전체 화면을 소유하도록 합니다. 그렇지 않으면 SwiftUI가 먼저 safe area를 적용하고 Compose는 인셋이 0인 상태가 됩니다.

ComposeView().ignoresSafeArea()

Scaffold가 대부분의 작업을 수행합니다

Scaffold(
    topBar = { TopAppBar(title = { Text(title) }) },          // 상태 표시줄에 대해 자체 패딩 처리
    bottomBar = { NavigationBar { /* ... */ } },              // 네비게이션 바에 대해 자체 패딩 처리
) { innerPadding ->
    LazyColumn(
        contentPadding = innerPadding,                         // 콘텐츠가 바 아래에서 스크롤됨
        modifier = Modifier.fillMaxSize(),
    ) { /* items */ }
}
  • 항상 innerPadding을 사용하세요. 리스트의 경우 contentPadding으로 전달하여 항목이 반투명 바 뒤에서 스크롤되도록 하고, 스크롤되지 않는 콘텐츠의 경우 Modifier.padding(innerPadding)을 사용하세요.
  • Material 3 바는 자체 인셋을 소비합니다. TopAppBar 위에 statusBarsPadding()을 추가하지 마세요.
  • 중첩된 Scaffold는 패딩을 두 배로 만듭니다. 내부 Scaffold에는 contentWindowInsets = WindowInsets(0)을 지정하거나 외부 콘텐츠에 consumeWindowInsets(innerPadding)을 적용하세요.

Scaffold가 없는 화면

Box(Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) {   // 배경이 화면을 채웁니다
    Column(Modifier.fillMaxSize().windowInsetsPadding(WindowInsets.safeDrawing)) { /* 콘텐츠 */ }
}

WindowInsets.safeDrawing은 상태 표시줄, 네비게이션 바, 디스플레이 컷아웃 및 키보드를 포함합니다. 제스처가 중요할 때는 safeContent를 사용하세요. 인셋 패딩은 콘텐츠를 소유하는 수준에서 한 번만 적용하고, 부모와 자식 모두에 적용하지 마세요.

키보드

  • 입력 화면: 스크롤 컨테이너에 Modifier.imePadding()을 사용하거나, 이미 IME를 포함하는 safeDrawing을 사용하세요.
  • 키보드 위에 있어야 하는 하단 버튼: Scaffold bottomBar에 Modifier.imePadding()과 함께 배치하거나 WindowInsets.ime.union(WindowInsets.navigationBars)를 사용하세요.
  • 콘텐츠를 스크롤 가능하게 만들어 포커스된 필드가 보이도록 하세요.

전체 화면 콘텐츠

이미지, 지도, 동영상 및 카메라 미리보기는 인셋을 무시하고 화면을 채워야 합니다. 컨트롤을 상단에 오버레이하고 WindowInsets.safeDrawing으로 컨트롤만 패딩 처리하세요.

시스템 바 대비

바는 투명하므로 아이콘 대비는 사용자의 책임입니다. Android에서 enableEdgeToEdge()는 시스템 테마에서 밝거나 어두운 아이콘을 선택합니다. 앱에 자체 테마 전환이 있는 경우 테마가 변경될 때 일치하는 SystemBarStyle과 함께 다시 호출하세요. 세 버튼 네비게이션에서 Android는 반투명 스크림을 추가합니다. 하단 바가 이미 단색 배경을 제공하지 않는 한 그대로 두세요.

광고 배너

하단 배너는 Scaffold bottomBar 슬롯 내부, 네비게이션 바 인셋 위에 배치되며, 콘텐츠가 튀지 않도록 높이가 예약됩니다. 배너가 제스처 바 아래에 위치하거나 네비게이션 컨트롤과 겹치지 않도록 하세요. 이는 레이아웃 버그이자 광고 정책 문제입니다.

모든 화면을 위한 체크리스트

  • 배경이 위아래 물리적 가장자리까지 도달합니다.
  • 상태 표시줄, 컷아웃, 네비게이션 바 또는 홈 인디케이터 아래에 텍스트나 컨트롤이 없습니다.
  • 마지막 리스트 항목이 하단 바 위로 완전히 스크롤될 수 있습니다.
  • 포커스된 텍스트 필드가 키보드가 열린 상태에서도 보입니다.
  • 가로 모드(컷아웃이 측면에 있음)와 어두운 테마에서 올바르게 보입니다.
  • 인셋이 한 번만 적용되고 두 배가 되지 않습니다.

Google의 edge-to-edge 스킬이 설치되어 있다면 이를 사용하여 Android 관련 문제를 해결하세요.

관련 스킬