안녕하세요! 최근 안드로이드 앱들을 살펴보면 기존 우리가 알고있던 다이얼로그와는 조금은 다르게 아래에서 위로 올라오는 구조로 되어있는 다이얼로그를 종종 볼 수 있습니다.
그래서 오늘은 그런 다이얼로그를 BottomSheetDialogFragment를 이용하여 간단히 구현하는 방법을 소개하고자 합니다.
Gradle 추가하기
implementation 'com.google.android.material:material:1.5.0'
코드예시
<Style XML>
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<!-- <item name="android:windowIsTranslucent">true</item> -->
<item name="android:windowIsFloating">false</item>
<item name="android:navigationBarColor">@color/background</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
</style>
<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@android:color/transparent</item>
</style>
- android:windowIsFloating
true : 자식 뷰만큼의 뷰사이즈를 가집니다.
false : 다이얼로그가 전체화면을 가집니다. - android:navigationBarColor
하단 네비게이션 색을 정합니다. 저같은 경우 다이얼로그가 흰색 바탕인 반면, 하단의 네비게이션바 색이 어두운 불투명색이기 때문에 네비게이션바 색을 배경색과 같게 설정했습니다. - android:windowSoftInputMode
다이얼로그 내에 EditText가 있는 경우 사용자가 작성시 화면을 Resize합니다. - bottomSheetStyle
모서리가 둥근 다이얼로그를 구현하기 위해 배경색을 투명으로하는 커스텀 Style 'bottomSheetStyleWrapper'를 적용합니다.
<Animation XML>
<style name="BottomSheetDialogAnimation">
<item name="android:windowEnterAnimation">@anim/slide_in_bottom</item>
<item name="android:windowExitAnimation">@anim/slide_out_bottom</item>
</style>
(저의 경우 큰 크기의 다이얼로그에서 Default 애니메이션이 심심하게 끝나, 직접 커스텀 애니메이션을 위와 같이 적용했습니다!)
<구현>
class MyBottomSheetDialog: BottomSheetDialogFragment() {
override fun getTheme(): Int = R.style.BottomSheetDialog // custom style
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.my_bottom_sheet_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 좌우 margin
((view.parent as View).layoutParams as CoordinatorLayout.LayoutParams).apply {
leftMargin = Utils.dpToPx(requireContext(), 7)
rightMargin = Utils.dpToPx(requireContext(), 7)
}
// dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) // 배경투명
dialog?.window?.attributes?.windowAnimations = R.style.BottomSheetDialogAnimation // 애니메이션
// 항상 확장된 상태 유지
val bottomSheet = dialog?.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
val behavior = BottomSheetBehavior.from<View>(bottomSheet!!)
behavior.skipCollapsed = true
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}
}
위에서 만든 XML 커스텀 스타일을 getTheme()을 구현하여 적용합니다.
만약 다이얼로그에 margin효과를 주고 싶다면, 부모 뷰의 layoutParams을 세팅하시면 됩니다.
또한 다이얼로그가 열리고 닫힐때의 커스텀 애니메이션을 적용하기 위해서는 window.attributes.windowAnimations를 이용해 적용하였습니다.
BottomSheetDialogFragment는 BottomSheetBehavior를 이용하는 구조로 되어있습니다. 그렇기 때문에 bottomSheet 및 bottomSheetBehavior 객체를 가져오는게 핵심이라고 생각합니다. 그래서 구글링을 해본결과 'com.google.android.material.R.id.design_bottom_sheet' 를 이용하면 위의 객체들을 가져올 수 있습니다!
저는 다이얼로그가 항상 확장된 상태를 유지시키기 위해 behavior.state를 STATE_EXPANDED로 주었습니다. 추가적으로 접히는 상태(collapsed)를 스킵하고 싶을때는 behavior.skipCollapsed를 true로 하시면 되겠습니다.
Tip) Dp를 Px로 변환하기
/**
* Dp -> Px
*/
fun dpToPx(context: Context, dp: Int): Int {
// val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.resources.displayMetrics)
// return px.roundToInt()
val density = context.resources.displayMetrics.density
return (dp * density).roundToInt()
}
참고 : https://developer-eungb.tistory.com/12
[Android/Kotlin] 안드로이드 BottomSheetDialogFragment 구현하기
새로 들어가는 프로젝트에서 처음으로 BottomSheetDialogFragment를 구현 할 일이 생겼다. BottomSheetDialog는 앱의 하단에서 올라오는 팝업창을 구현할 때 사용한다. 라이브러리 의존성 추가 implementation 'co
developer-eungb.tistory.com
'Android' 카테고리의 다른 글
[안드로이드 / Kotlin] 코루틴(Coroutine) (0) | 2022.03.21 |
---|---|
[안드로이드 / Kotlin] 타이머(Timer) 구현하기 (0) | 2022.03.18 |
[안드로이드 / Kotlin] RecyclerView Drag&Drop / Swipe 구현 (0) | 2022.03.15 |
[안드로이드 / Kotlin] 저전력 블루투스 BLE(3), 기기 연결 (0) | 2022.03.15 |
[안드로이드 / Kotlin] 화면 전환 시 작업 처리, 구성 변경 처리(onConfigurationChanged) (0) | 2022.03.06 |