안드로이드 개발시 소프트키 = 내비게이션 바 라는것이 존재합니다.
소프트 키란 일부 스마트폰 ( 사실상 대부분의 핸드폰)이 하드웨어의 하단에 홈,백버튼이 없습니다.
이런 경우 터치가 가능하게 만들어 놓은 키보드 입니다.
방식은 2가지로 버튼형식, 스와이프 제스처형식 입니다.
개발을 진행하다 보면 statusBar를 투명하게 만들어야 하는 경우가 생기고 그러기 위해서는
WindowCompat.setDecorFitsSystemWindows(window, false)
다음과 같은 코드로 뷰를 확장 시키게 됩니다.
이번 포스팅에서 다룰 케이스는
뷰 확장 + 소프트키를 다룰 경우의 케이스입니다.
먼저 문제점은 뷰가 위 아래로 전부 확장된 상태에서 소프트 키를 사용하게 되면 바텀 네비게이션, 최 하단의 ok버튼, 리스트, 바텀시트 등등이 소프트키에 가려지는 상황이 벌어집니다.
이것에 대해서 다룬 포스팅은 https://medium.com/androiddevelopers/windowinsets-listeners-to-layouts-8f9ccc8fa4d1 가 있었습니다.
단순히 padding값을 주기엔 소프트 키의 높이가 전부 다르고 바텀 네비게이션의 경우 원치 않은 공간이 벌어질 수 있습니다.
해결책
ViewPadding에 대한 class를 하나 만듭니다.
fun bottomPadding(view: View) {
view.doOnApplyWindowInsets { view, insets, padding ->
view.updatePadding(
bottom = padding.bottom + insets.systemWindowInsetBottom
)
}
}
fun View.doOnApplyWindowInsets(f: (View, WindowInsets, InitialPadding) -> Unit) {
val initialPadding = recordInitialPaddingForView(this)
setOnApplyWindowInsetsListener { v, insets ->
f(v, insets, initialPadding)
insets
}
requestApplyInsetsWhenAttached()
}
data class InitialPadding(
val left: Int, val top: Int,
val right: Int, val bottom: Int
)
fun recordInitialPaddingForView(view: View) = InitialPadding(
view.paddingLeft, view.paddingTop, view.paddingRight, view.paddingBottom
)
fun View.requestApplyInsetsWhenAttached() {
if (isAttachedToWindow) {
requestApplyInsets()
} else {
addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
v.removeOnAttachStateChangeListener(this)
v.requestApplyInsets()
}
override fun onViewDetachedFromWindow(v: View) = Unit
})
}
}
사용법
class VideoActivity : AppCompatActivity() {
private lateinit var binding: ActivityVideoBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//videoMainContainer는 xml에서 가장 밑바닥인 Constraintlayout입니다.
bottomPadding(binding.videoMainContainer)
}
소프트키에 대응해야하는 Activity , Fragment에 bottomPadding을 호출합니다.