관리 메뉴

나만을 위한 블로그

[Android Compose] Material 3 버전의 BottomSheet 구현하기 본문

Android/Compose

[Android Compose] Material 3 버전의 BottomSheet 구현하기

참깨빵위에참깨빵_ 2023. 8. 24. 22:38
728x90
반응형

먼저 앱 gradle에 라이브러리 의존성을 추가한다.

 

implementation(platform("androidx.compose:compose-bom:2023.06.01"))

 

그리고 적당한 이미지를 하나 준비하고 drawable 폴더에 넣어둔다. 아래는 액티비티의 전체 코드다.

 

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.example.composeprac.R
import com.example.composeprac.bottom_sheet.ui.theme.ComposePracTheme

@OptIn(ExperimentalMaterial3Api::class)
class BottomSheetTestActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposePracTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    val sheetState = rememberModalBottomSheetState()
                    var isSheetOpen by rememberSaveable {
                        mutableStateOf(false)
                    }

                    Box(
                        modifier = Modifier.fillMaxSize(),
                        contentAlignment = Alignment.Center
                    ) {
                        Button(onClick = {
                            isSheetOpen = true
                        }) {
                            Text("Bottom Sheet 열기")
                        }
                    }

                    if (isSheetOpen) {
                        ModalBottomSheet(
                            sheetState = sheetState,
                            onDismissRequest = {
                                isSheetOpen = false
                            },
                        ) {
                            Image(
                                painter = painterResource(id = R.drawable.test),
                                contentDescription = null
                            )
                        }
                    }
                }
            }
        }
    }
}

 

이후 실행하면 아래와 같이 작동한다. 자주 본 바텀 시트의 동작 그대로다.

 

 

 

딱히 분석할 코드가 없다. 그리고 ModalBottomSheet가 아닌 다른 바텀 시트도 확인해 본다.

 

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Button
import androidx.compose.material3.BottomSheetScaffold
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.composeprac.R
import com.example.composeprac.bottom_sheet.ui.theme.ComposePracTheme
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
class BottomSheetTestActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposePracTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    val scaffoldState = rememberBottomSheetScaffoldState()
                    val scope = rememberCoroutineScope()

                    Box(
                        modifier = Modifier.fillMaxSize(),
                        contentAlignment = Alignment.Center
                    ) {
                        Button(onClick = {
                            scope.launch {
                                scaffoldState.bottomSheetState.expand()
                            }
                        }) {
                            Text("Bottom Sheet 열기")
                        }
                    }

                    BottomSheetScaffold(
                        scaffoldState = scaffoldState,
                        sheetContent = {
                            Image(
                                painter = painterResource(id = R.drawable.test),
                                contentDescription = null
                            )
                        },
                        sheetPeekHeight = 0.dp
                    ) {}
                }
            }
        }
    }
}


BottomSheetScaffold로 바뀌었는데 이렇게 하고 실행하면 아래와 같다. 각 영상을 보면 차이를 알 수 있다.

 

 

 

영상으로는 잘 안보이는데, ModalBottomSheet를 사용했을 때는 바텀시트 바깥 영역을 클릭하면 바텀시트가 밑으로 사라졌다. 그러나 BottomSheetScaffold를 사용하면 바깥 영역을 클릭해도 바텀시트가 사라지지 않는다.

또한 배경의 dim 처리 여부도 다르다. ModalBottomSheet는 뒷배경이 dim 처리되면서 바텀시트가 표시되지만 BottomSheetScaffold는 그렇지 않은 걸 확인할 수 있다.

 

2번째 코드에서 볼 점이라면 sheetPeekHeight를 0.dp로 설정한 건데, 이것은 0.dp를 명시하지 않으면 바텀시트를 내려도 화면 하단에 상단 부분이 조금 보이게 된다. 해당 속성을 없애고 빌드해보면 알 수 있을 것이다.

2번째 코드 역시 sheetPeekHeight 이외에 분석할 만한 코드는 없기 때문에 넘어간다. 각 바텀시트의 특성을 확인하고 상황에 맞게 사용하자.

반응형
Comments