Skip to content

Instantly share code, notes, and snippets.

@xvadsan
Last active December 23, 2020 11:27
Show Gist options
  • Save xvadsan/e16829c75c3ac8030c7a6c3239a6e7ab to your computer and use it in GitHub Desktop.
Save xvadsan/e16829c75c3ac8030c7a6c3239a6e7ab to your computer and use it in GitHub Desktop.
KeyboardEventListener
override fun onResume() {
super.onResume()
KeyboardEventListener(this) { isOpen -> // handle event }
}
fun Activity.getRootView(): View {
return findViewById(android.R.id.content)
}
fun Context.convertDpToPx(dp: Float): Float {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
this.resources.displayMetrics
)
}
fun Activity.isKeyboardOpen(): Boolean {
val visibleBounds = Rect()
this.getRootView().getWindowVisibleDisplayFrame(visibleBounds)
val contentViewTop = window.findViewById<View>(Window.ID_ANDROID_CONTENT).getTop()
val heightDiff = getRootView().height - visibleBounds.height()
val marginOfError = this.convertDpToPx(50F).roundToInt()
return heightDiff > marginOfError
}
fun Activity.isKeyboardClosed(): Boolean {
return !this.isKeyboardOpen()
}
fun Activity.getRootView(): View {
return findViewById(android.R.id.content)
}
fun Context.convertDpToPx(dp: Float): Float {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
this.resources.displayMetrics
)
}
fun Activity.isKeyboardOpen(): Boolean {
val visibleBounds = Rect()
this.getRootView().getWindowVisibleDisplayFrame(visibleBounds)
val contentViewTop = window.findViewById<View>(Window.ID_ANDROID_CONTENT).getTop()
val heightDiff = getRootView().height - visibleBounds.height()
val marginOfError = this.convertDpToPx(50F).roundToInt()
return heightDiff > marginOfError
}
fun Activity.isKeyboardClosed(): Boolean {
return !this.isKeyboardOpen()
}
import android.view.ViewTreeObserver
import androidx.annotation.CallSuper
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
class KeyboardEventListener(
private val activity: AppCompatActivity,
private val callback: (isOpen: Boolean) -> Unit
) : LifecycleObserver {
private val listener = object : ViewTreeObserver.OnGlobalLayoutListener {
private var lastState: Boolean = activity.isKeyboardOpen()
override fun onGlobalLayout() {
val isOpen = activity.isKeyboardOpen()
if (isOpen == lastState) {
return
} else {
dispatchKeyboardEvent(isOpen)
lastState = isOpen
}
}
}
init {
// Dispatch the current state of the keyboard
dispatchKeyboardEvent(activity.isKeyboardOpen())
// Make the component lifecycle aware
activity.lifecycle.addObserver(this)
registerKeyboardListener()
}
private fun registerKeyboardListener() {
activity.getRootView().viewTreeObserver.addOnGlobalLayoutListener(listener)
}
private fun dispatchKeyboardEvent(isOpen: Boolean) {
when {
isOpen -> callback(true)
!isOpen -> callback(false)
}
}
@OnLifecycleEvent(value = Lifecycle.Event.ON_PAUSE)
@CallSuper
fun onLifecyclePause() {
unregisterKeyboardListener()
}
private fun unregisterKeyboardListener() {
activity.getRootView().viewTreeObserver.removeOnGlobalLayoutListener(listener)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment