Android 15에서 더 넓은 화면 시행 처리

1. 시작하기 전에

SociaLite는 다양한 Android 플랫폼 API를 사용하여 소셜 네트워크 앱에서 흔히 보는 기능을 구현하는 방법을 보여주므로 다양한 Jetpack API를 활용하여 더 많은 기기에서 안정적으로 작동하면서도 코드는 더 적게 필요한 복잡한 기능을 달성할 수 있습니다.

이 Codelab에서는 SociaLite 앱을 Android 15 더 넓은 화면 시행과 호환되도록 하고 앱을 하위 호환 방식으로 더 넓은 화면으로 설정하는 방법을 설명합니다. 더 넓은 화면으로 설정한 후 SociaLite는 기기와 탐색 모드에 따라 다음과 같이 표시됩니다.

3버튼 탐색의 SociaLite 앱

동작 탐색의 SociaLite 앱

3버튼 탐색이 포함된 SociaLite

동작 탐색이 포함된 SociaLite

대형 화면 기기에서 SociaLite 앱

대형 화면 기기에서 SociaLite

기본 요건

  • 기본적인 Kotlin 지식
  • Android 스튜디오 설정 Codelab 완료 또는 Android 스튜디오 사용 방법과 에뮬레이터나 Android 15를 실행하는 실제 기기에서 앱을 테스트하는 방법에 관한 지식

학습할 내용

  • Android 15 더 넓은 화면 변경사항 처리 방법
  • 앱을 하위 호환 방식으로 더 넓은 화면으로 설정하는 방법

필요한 항목

  • Android 스튜디오 최신 버전
  • Android 15 베타 1 이상을 실행하는 테스트 기기나 에뮬레이터
  • Android 15 베타 1 SDK 이상

2. 시작 코드 가져오기

  1. GitHub에서 시작 코드를 다운로드합니다.

또는 저장소를 클론하고 codelab_improve_android_experience_2024 브랜치를 확인합니다.

$ git clone git@github.com:android/socialite.git
$ cd socialite
$ git checkout codelab_improve_android_experience_2024
  1. Android 스튜디오에서 SociaLite를 열고 Android 15 기기나 에뮬레이터에서 앱을 실행합니다. 화면이 다음 중 하나와 같이 표시됩니다.

3버튼 탐색이 포함된 SociaLite

동작 탐색이 포함된 SociaLite

3버튼 탐색

동작 탐색

대형 화면 기기에서 SociaLite

대형 화면

  1. 채팅 페이지에서 대화의 하나를 선택합니다(예: 반려견이 포함된 대화).

3버튼 탐색이 포함된 반려견 채팅 메시지

동작 탐색이 포함된 반려견 채팅 메시지

3버튼 탐색이 포함된 반려견 채팅 메시지

동작 탐색이 포함된 반려견 채팅 메시지

3. Android 15에서 앱을 더 넓은 화면으로 설정

더 넓은 화면이란 무엇인가요?

앱이 시스템 표시줄 뒤에 그려질 수 있으므로 사용자 환경이 깔끔해지고 디스플레이 공간을 최대한 사용할 수 있습니다. 이를 더 넓은 화면을 활용한다고 합니다.

더 넓은 화면을 활용하는 앱 GIF

Android 15 더 넓은 화면 변경사항 처리 방법

Android 15 전에는 기본적으로 앱의 UI가 상태 표시줄과 탐색 메뉴 등 시스템 표시줄 영역을 피하도록 배치되어야 했습니다. 앱에서 더 넓은 화면을 활용하기로 선택했습니다. 앱에 따라 이러한 선택은 사소한 것부터 번거로운 것까지 다양할 수 있습니다.

Android 15부터는 앱이 기본적으로 더 넓은 화면을 활용하게 됩니다. 기본적으로 다음과 같이 표시됩니다.

  • 3버튼 탐색 메뉴가 반투명입니다.
  • 동작 탐색 메뉴가 투명합니다.
  • 상태 표시줄이 투명합니다.
  • 콘텐츠에 인셋이나 패딩을 적용하지 않는 한 콘텐츠는 탐색 메뉴와 상태 표시줄, 자막 표시줄 등 시스템 표시줄 뒤에 그려집니다.

이렇게 하면 앱 품질 향상의 수단으로 더 넓은 화면을 간과하지 않고 앱이 더 넓은 화면을 활용하는 데 필요한 작업을 줄일 수 있습니다. 하지만 이 변경으로 앱에 부정적인 영향을 미칠 수 있습니다. 타겟 SDK를 Android 15로 업그레이드한 후 SociaLite 내에서 발생하는 두 가지 부정적인 영향을 예로 들어 보겠습니다.

타겟 SDK 값을 Android 15로 변경

  1. SociaLite 앱의 build.gradle 파일 내에서 타겟 SDK 버전과 컴파일 SDK 버전을 Android 15나 VanillaIceCream으로 변경합니다.

Android 15 안정화 버전 출시 전에 이 Codelab을 진행하는 경우 코드는 다음과 같이 표시됩니다.

android {
    namespace = "com.google.android.samples.socialite"
    compileSdkPreview = "VanillaIceCream"

    defaultConfig {
        applicationId = "com.google.android.samples.socialite"
        minSdk = 21
        targetSdkPreview = "VanillaIceCream"
        ...
    }
...
}

Android 15 안정화 버전 출시 후 이 Codelab을 진행하는 경우에는 코드가 다음과 같이 표시됩니다.

android {
    namespace = "com.google.android.samples.socialite"
    compileSdk = 35

    defaultConfig {
        applicationId = "com.google.android.samples.socialite"
        minSdk = 21
        targetSdk = 35
        ...
    }
...
}
  1. SociaLite를 다시 빌드하고 다음 문제를 확인합니다.
  • 3버튼 탐색 배경 보호가 탐색 메뉴와 일치하지 않습니다. 동작 탐색을 위해 개발자의 개입 없이 채팅 화면이 더 넓은 화면으로 보입니다. 하지만 3버튼 탐색 배경 보호가 있으며 이는 삭제해야 합니다.

3버튼 탐색이 포함된 채팅 화면

동작 탐색이 포함된 채팅 화면

3버튼 탐색이 포함된 채팅 화면

동작 탐색이 포함된 채팅 화면

  • 가려진 UI. 대화의 하단 UI 요소가 탐색 메뉴에 가려져 있습니다. 이 부분이 3버튼 탐색에서 가장 분명하게 나타납니다.

3버튼 탐색이 포함된 반려견 채팅 메시지

동작 탐색이 포함된 반려견 채팅 메시지

3버튼 탐색이 포함된 반려견 채팅 메시지

동작 탐색이 포함된 반려견 채팅 메시지

SociaLite 문제 해결

기본 3버튼 탐색 배경 보호를 삭제하려면 다음 단계를 따르세요.

  1. MainActivity.kt 파일에서 window.isNavigationBarContrastEnforced 속성을 false로 설정하여 기본 배경 보호를 삭제합니다.
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        installSplashScreen()
        super.onCreate(savedInstanceState)
        setContent {
            // Add this block:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                window.isNavigationBarContrastEnforced = false
            }
        }
    }
    ...
}

window.isNavigationBarContrastEnforced는 완전히 투명한 배경이 요청될 때 탐색 메뉴의 대비가 충분한지 확인합니다. 이 속성을 false로 설정하면 사실상 3버튼 탐색 배경을 투명으로 설정하는 것입니다. window.isNavigationBarContrastEnforced는 3버튼 탐색에만 영향을 미치며 동작 탐색에는 영향을 미치지 않습니다.

  1. Android 15 기기에서 앱을 다시 실행하고 대화의 하나를 확인합니다. 이제 타임라인, 채팅, 설정 화면이 모두 더 넓은 화면으로 표시됩니다. 앱의 NavigationBar(타임라인, 채팅, 설정 버튼 포함)가 시스템의 투명한 3버튼 탐색 메뉴 뒤에 그려집니다.

3버튼 탐색과 밴딩이 삭제된 채팅 화면

동작 탐색의 반려견 대화

밴딩이 삭제된 채팅 화면.

동작 탐색 변경사항 없음

하지만 대화의 InputBar는 여전히 시스템 표시줄에 가려집니다. 이 문제를 해결하려면 인셋을 적절히 처리해야 합니다.

3버튼 탐색의 반려견 대화

동작 탐색의 반려견 대화

3버튼 탐색의 반려견 대화 하단의 입력란이 시스템의 탐색 메뉴에 가려져 있습니다.

동작 탐색의 반려견 대화. 하단의 입력란이 시스템의 탐색 메뉴에 가려져 있습니다.

SociaLite에서는 InputBar가 가려져 있습니다. 실제로 가로 모드로 회전하거나 대형 화면 기기를 사용할 때는 상단과 하단, 오른쪽과 왼쪽의 요소가 가려져 있을 수 있습니다. 이러한 모든 사용 사례에서 인셋 처리 방법을 고려해야 합니다. SociaLite의 경우 패딩을 적용하여 탭 가능한 InputBar 콘텐츠를 위로 올립니다.

인셋을 적용하여 가려진 UI를 수정하려면 다음 단계를 따르세요.

  1. ui/chat/ChatScreen.kt 파일로 이동하여 178번 줄 부근에서 ChatContent 컴포저블을 찾습니다. 여기에는 대화 화면의 UI가 포함되어 있습니다. ChatContentScaffold를 활용하여 UI를 쉽게 구성합니다. 기본적으로 Scaffold는 시스템 표시줄의 깊이와 같은 시스템 UI에 관한 정보를 Scaffold의 패딩 값(innerPadding 매개변수)과 함께 사용할 수 있는 인셋으로 제공합니다. ScaffoldinnerPadding을 사용하여 패딩을 InputBar에 추가합니다.
  2. 214번 줄 부근에서 ChatContent 내의 InputBar를 찾습니다. 이는 사용자가 메시지를 작성하는 UI를 만드는 맞춤 컴포저블입니다. 미리보기는 다음과 같습니다.

PreviewInputBar

InputBarcontentPadding을 가져와서 나머지 UI가 포함된 Row 컴포저블에 패딩으로 적용합니다. 패딩은 Row 컴포저블의 모든 측면에 적용됩니다. 432번 줄 부근에서 이를 확인할 수 있습니다. 다음은 참조용 InputBar 컴포저블입니다(이 코드를 추가하면 안 됨).

// Don't add this code because it's only for reference.
@Composable
private fun InputBar(
    contentPadding: PaddingValues,
    ...,
) {
    Surface(...) {
        Row(
            modifier = Modifier
                .padding(contentPadding)
            ...
        ) {
            IconButton(...) { ... } // take picture
            IconButton(...) { ... } // attach picture
            TextField(...) // write message
            FilledIconButton(...){ ... } // send message
            }
        }
    }
}
  1. ChatContentInputBar로 다시 이동하고 시스템 표시줄 인셋을 사용하도록 contentPadding을 변경합니다. 220번 줄 부근에 있습니다.
InputBar(
    ...
    contentPadding = innerPadding, //Add this line.
    // contentPadding = PaddingValues(0.dp), // Remove this line.
    ...
 )
  1. Android 15 기기에서 앱을 다시 실행합니다.

3버튼 탐색의 반려견 대화

동작 탐색의 반려견 대화

인셋이 잘못 적용된 3버튼 탐색의 반려견 대화

인셋이 잘못 적용된 동작 탐색의 반려견 대화

시스템 표시줄에 버튼이 더 이상 가려지지 않도록 하단 패딩이 적용되었지만 상단 패딩도 적용되었습니다. 상단 패딩은 TopAppBar 및 시스템 표시줄의 깊이를 포함합니다. Scaffold는 패딩 값을 콘텐츠에 전달하여 상단 앱 바는 물론 시스템 표시줄을 피할 수 있도록 합니다.

  1. 상단 패딩 문제를 해결하려면 innerPadding PaddingValues의 사본을 만들고 상단 패딩을 0.dp로 설정한 후 수정된 사본을 contentPadding에 전달합니다.
InputBar(
    ...
    contentPadding = innerPadding.copy(layoutDirection, top = 0.dp), //Add this line.
    // contentPadding = innerPadding, // Remove this line.
    ...
 )
  1. Android 15 기기에서 앱을 다시 실행합니다.

3버튼 탐색의 반려견 대화

동작 탐색의 반려견 대화

인셋이 올바르게 적용된 3버튼 탐색의 반려견 대화

인셋이 올바르게 적용된 동작 탐색의 반려견 대화

축하합니다. SociaLite를 Android 15 더 넓은 화면 플랫폼 변경사항과 호환되도록 했습니다. 이제 SociaLite를 하위 호환 방식으로 더 넓은 화면으로 설정하는 방법을 알아봅니다.

4. SociaLite를 하위 호환 방식으로 더 넓은 화면으로 설정

SociaLite는 이제 Android 15에서 더 넓은 화면으로 설정되지만 여전히 이전 Android 기기에서는 더 넓은 화면으로 설정되지 않습니다. 이전 Android 기기에서 SociaLite를 더 넓은 화면으로 설정하려면 MainActivity.kt 파일에서 콘텐츠를 설정하기 전에 enableEdgeToEdge를 호출하세요.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        installSplashScreen()
        enableEdgeToEdge() // Add this line.
        window.isNavigationBarContrastEnforced = false
        super.onCreate(savedInstanceState)
        setContent {... }
    }
}

enableEdgeToEdge 가져오기는 import androidx.activity.enableEdgeToEdge입니다. 종속 항목은 AndroidX Activity 1.8.0 이상입니다.

하위 호환 방식으로 앱을 더 넓은 화면으로 설정하는 방법과 인셋을 처리하는 방법에 관한 자세한 내용은 다음 가이드를 참고하세요.

이로써 개발자 과정의 더 넓은 화면 부분이 마무리되었습니다. 다음 섹션은 선택사항이며 앱에 적용할 수 있는 더 넓은 화면 관련 기타 고려사항을 설명합니다.

5. 선택사항: 더 넓은 화면 추가 고려사항

아키텍처 전반에 걸친 인셋 처리

구성요소

SociaLite의 여러 구성요소가 타겟 SDK 값 변경 후에도 변경되지 않았습니다. SociaLite는 권장사항에 따라 설계되었으므로 이 플랫폼 변경을 쉽게 처리할 수 있습니다. 권장사항은 다음과 같습니다.

  • 인셋을 자동으로 적용하므로 TopAppBar, BottomAppBar, NavigationBar와 같은 Material Design 3 구성요소를 사용합니다(androidx.compose.material3).
  • 앱이 대신 Compose에서 Material 2 구성요소(androidx.compose.material)를 사용한다면 이러한 구성요소는 인셋 자체를 자동으로 처리하지 않습니다. 하지만 인셋에 액세스하여 수동으로 적용할 수 있습니다. androidx.compose.material 1.6.0 이상에서 windowInsets 매개변수를 사용하여 BottomAppBar, TopAppBar, BottomNavigation, NavigationRail에 인셋을 수동으로 적용합니다. 마찬가지로 Scaffold에는 contentWindowInsets 매개변수를 사용합니다. 그 외에는 수동으로 인셋을 패딩으로 적용합니다.
  • 앱에서 뷰 및 Material 구성요소(com.google.android.material)를 사용한다면 뷰 기반 Material 구성요소(예: BottomNavigationView, BottomAppBar, NavigationRailView, NavigationView)는 대부분 인셋을 처리하므로 추가 작업이 필요하지 않을 수 있습니다. 하지만 AppBarLayout을 사용하는 경우에는 android:fitsSystemWindows="true"를 추가해야 합니다.
  • 앱에서 뷰와 BottomSheet, SideSheet 또는 맞춤 컨테이너를 사용하는 경우 ViewCompat.setOnApplyWindowInsetsListener를 사용하여 패딩을 적용합니다. RecyclerView의 경우에는 이 리스너를 사용하여 패딩을 적용하고 clipToPadding="false"도 추가합니다.
  • 복잡한 UI에는 Surface가 아닌 Scaffold(또는 NavigationSuiteScaffoldListDetailPaneScaffold)를 사용합니다. Scaffold를 사용하면 TopAppBar, BottomAppBar, NavigationBar, NavigationRail을 쉽게 배치할 수 있습니다.

콘텐츠 스크롤

앱에는 목록이 포함될 수 있으며 Android 15 변경사항으로 목록의 마지막 항목이 시스템의 탐색 메뉴에 가려질 수 있습니다.

마지막 목록 항목이 3버튼 탐색으로 가려진 앱

목록의 마지막 항목이 3버튼 탐색으로 가려진 것을 보여줍니다.

Compose로 콘텐츠 스크롤

TextField를 사용하지 않는 한 Compose에서 LazyColumncontentPadding을 사용하여 마지막 항목에 공간을 추가합니다.

Scaffold { innerPadding ->
    LazyColumn(
        contentPadding = innerPadding
    ) {
        // Content that does not contain TextField
    }
}

마지막 목록 항목이 3버튼 탐색으로 가려지지 않은 앱

목록의 마지막 항목이 3버튼 탐색으로 가려지지 않은 것을 보여줍니다.

TextField의 경우 Spacer를 사용하여 LazyColumn의 마지막 TextField를 그립니다. 자세한 내용은 인셋 사용을 참고하세요.

LazyColumn(
    Modifier.imePadding()
) {
    // Content with TextField
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

뷰를 사용하여 콘텐츠 스크롤

RecyclerViewNestedScrollView의 경우 android:clipToPadding="false"를 추가합니다.

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recycler"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    app:layoutManager="LinearLayoutManager" />

setOnApplyWindowInsetsListener를 사용하여 창 인셋에서 왼쪽, 오른쪽, 하단 패딩을 제공합니다.

ViewCompat.setOnApplyWindowInsetsListener(binding.recycler) { v, insets ->
    val i = insets.getInsets(
        WindowInsetsCompat.Type.systemBars() + WindowInsetsCompat.Type.displayCutout()
    )
    v.updatePadding(
        left = i.left,
        right = i.right,
        bottom = i.bottom + bottomPadding,
    )
    WindowInsetsCompat.CONSUMED
}

LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS 사용

SDK 35를 타겟팅하기 전에 SociaLite는 가로 모드에서 다음과 같이 표시되었습니다. 왼쪽 가장자리에 카메라 컷아웃을 처리하는 큰 흰색 상자가 있습니다. 3버튼 탐색에서 버튼은 오른쪽에 있습니다.

가로 모드의 SociaLite 앱

SDK 35를 타겟팅한 후 SociaLite는 다음과 같이 표시됩니다. 더 이상 왼쪽 가장자리에 카메라 컷아웃을 고려하는 큰 흰색 상자가 없습니다. 이 효과를 달성하기 위해 Android에서는 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS를 자동으로 설정합니다. 가로 모드의 SociaLite 앱

앱에 따라 여기서 인셋을 처리할 수도 있습니다.

SociaLite에서 이렇게 하려면 다음 단계를 따르세요.

  1. ui/ContactRow.kt 파일에서 Row 컴포저블을 찾습니다.
  2. 디스플레이 컷아웃을 처리하도록 패딩을 수정합니다.
@Composable
fun ChatRow(
   chat: ChatDetail,
   onClick: (() -> Unit)?,
   modifier: Modifier = Modifier,
) {
   // Add layoutDirection, displayCutout, startPadding, and endPadding.
   val layoutDirection = LocalLayoutDirection.current
   val displayCutout = WindowInsets.displayCutout.asPaddingValues()
   val startPadding = displayCutout.calculateStartPadding(layoutDirection)
   val endPadding = displayCutout.calculateEndPadding(layoutDirection)
   Row(
       modifier = modifier
           ...
           // .padding(16.dp) // Remove this line.
           // Add this block:
           .padding(
               PaddingValues(
                   top = 16.dp,
                   bottom = 16.dp,
                   // Ensure content is not occluded by display cutouts
                   // when rotating the device.
                   start = startPadding.coerceAtLeast(16.dp),
                   end = endPadding.coerceAtLeast(16.dp)
               )
           ),
       ...
   ) { ... }

디스플레이 컷아웃 처리 후 SociaLite는 다음과 같습니다.

가로 모드의 SociaLite 앱

개발자 옵션 화면의 디스플레이 컷아웃 아래에서 다양한 디스플레이 컷아웃 구성을 테스트할 수 있습니다.

앱에 LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULTLAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER, LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES를 사용하는 플로팅 창(예: 활동)이 있으면 Android에서는 Android 15 베타 2부터 이러한 컷아웃 모드를 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS로 해석합니다. 이전 Android 15 베타 1에서는 앱이 다운되었습니다.

자막 표시줄도 시스템 표시줄입니다

자막 표시줄도 시스템 표시줄입니다. 상단 제목 표시줄 등 자유 형식 창의 시스템 UI 창 장식을 설명하기 때문입니다. Android 스튜디오의 데스크톱 에뮬레이터 내에서 자막 표시줄을 확인할 수 있습니다. 다음 스크린샷에서 자막 표시줄은 앱 상단에 있습니다.

자막 표시줄을 보여주는 에뮬레이터

Compose에서 ScaffoldPaddingValues, safeContent, safeDrawing 또는 내장 WindowInsets.systemBars를 사용하는 경우 앱이 예상대로 표시됩니다. 하지만 statusBar를 사용하여 인셋을 처리하는 경우 앱 콘텐츠가 예상대로 표시되지 않을 수 있습니다. 상태 표시줄이 자막 표시줄을 고려하지 않기 때문입니다.

뷰에서 WindowInsetsCompat.systemBars를 사용하여 수동으로 인셋을 처리하는 경우 앱이 예상대로 표시됩니다. WindowInsetsCompat.statusBars를 사용하여 인셋을 수동으로 처리한다면 앱이 예상대로 표시되지 않을 수 있습니다. 상태 표시줄이 자막 표시줄이 아니기 때문입니다.

몰입형 모드의 앱

몰입형 모드의 화면은 Android 15의 더 넓은 화면 시행에 대부분 영향을 받지 않습니다. 몰입형 앱은 이미 더 넓은 화면을 활용하기 때문입니다.

시스템 표시줄 보호

동작 탐색에는 투명한 표시줄, 3버튼 탐색에는 반투명 또는 불투명 표시줄을 사용하고 싶을 수 있습니다.

Android 15에서는 반투명 3버튼 탐색이 기본값입니다. 플랫폼에서 window.isNavigationBarContrastEnforced 속성으로 true로 설정하기 때문입니다. 동작 탐색은 투명하게 유지됩니다.

3버튼 탐색의 앱

기본적으로 반투명인 3버튼 탐색

일반적으로 3버튼 탐색은 반투명이면 됩니다. 하지만 때에 따라 앱에 불투명 3버튼 탐색이 필요할 수 있습니다. 먼저 window.isNavigationBarContrastEnforced 속성을 false로 설정합니다. 그런 다음 뷰의 경우 WindowInsetsCompat.tappableElement를 사용하고 Compose의 경우 WindowInsets.tappableElement를 사용합니다. 값이 0이면 사용자가 동작 탐색을 사용하는 것입니다. 0이 아니면 사용자가 3버튼 탐색을 사용하는 것입니다. 사용자가 3버튼 탐색을 사용한다면 탐색 메뉴 뒤에 뷰나 상자를 그립니다. Compose 예는 다음과 같습니다.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            window.isNavigationBarContrastEnforced = false
            MyTheme {
                Surface(...) {
                    MyContent(...)
                    ProtectNavigationBar()
                }
            }
        }
    }
}

// Use only if required.
@Composable
fun ProtectNavigationBar(modifier: Modifier = Modifier) {
   val density = LocalDensity.current
   val tappableElement = WindowInsets.tappableElement
   val bottomPixels = tappableElement.getBottom(density)
   val usingTappableBars = remember(bottomPixels) {
       bottomPixels != 0
   }
   val barHeight = remember(bottomPixels) {
       tappableElement.asPaddingValues(density).calculateBottomPadding()
   }

   Column(
       modifier = modifier.fillMaxSize(),
       verticalArrangement = Arrangement.Bottom
   ) {
       if (usingTappableBars) {
           Box(
               modifier = Modifier
                   .background(MaterialTheme.colorScheme.background)
                   .fillMaxWidth()
                   .height(barHeight)
           )
       }
   }
}

3버튼 탐색의 앱

불투명 3버튼 탐색

6. 솔루션 코드 검토

MainActivity.kt 파일의 onCreate 메서드는 다음과 같습니다.

class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       installSplashScreen()
       enableEdgeToEdge()
       window.isNavigationBarContrastEnforced = false
       super.onCreate(savedInstanceState)
       setContent {
           Main(
               shortcutParams = extractShortcutParams(intent),
           )
       }
   }
}

ChatScreen.kt 파일 내 ChatContent 컴포저블은 다음과 같이 인셋을 처리해야 합니다.

private fun ChatContent(...) {
   ...
   Scaffold(...) { innerPadding ->
       Column {
           ...
           InputBar(
               input = input,
               onInputChanged = onInputChanged,
               onSendClick = onSendClick,
               onCameraClick = onCameraClick,
               onPhotoPickerClick = onPhotoPickerClick,
               contentPadding = innerPadding.copy(
                    layoutDirection, top = 0.dp
                ),
               sendEnabled = sendEnabled,
               modifier = Modifier
                   .fillMaxWidth()
                   .windowInsetsPadding(
                       WindowInsets.ime.exclude(WindowInsets.navigationBars)
                    ),
            )
       }
   }
}

솔루션 코드는 main 브랜치에서 확인할 수 있습니다. 이미 SociaLite를 다운로드 했다면 다음을 실행하세요.

git checkout main

다운로드하지 않은 경우 코드를 다시 다운로드하여 직접 또는 git을 통해 main 브랜치를 확인할 수 있습니다.

git clone git@github.com:android/socialite.git