Skip to content

Instantly share code, notes, and snippets.

@Tagakov
Created October 30, 2018 13:37
Show Gist options
  • Save Tagakov/9bfc1cd6b31ef22cf489055715ae2944 to your computer and use it in GitHub Desktop.
Save Tagakov/9bfc1cd6b31ef22cf489055715ae2944 to your computer and use it in GitHub Desktop.
Allows to hide and show keyboard with notification after successful hiding or showing
@Reusable
class RxKeyboardManager(private val activity: Activity, private val mainThread: Scheduler, private val imm: InputMethodManager) {
val keyboardStates = Observable.create<Boolean>({
val globalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener { it.onNext(isKeyboardShown()) }
it.setCancellation { activity.window.decorView.viewTreeObserver.removeOnGlobalLayoutListener(globalLayoutListener) }
activity.window.decorView.viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener)
}, Emitter.BackpressureMode.LATEST)
.distinctUntilChanged()
.subscribeOn(mainThread)
.share()
fun isKeyboardShown(): Boolean {
val rootView = activity.window.decorView
/* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
val SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128
val r = Rect()
rootView.getWindowVisibleDisplayFrame(r)
val dm = rootView.resources.displayMetrics
/* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
val heightDiff = rootView.bottom - r.bottom
/* Threshold size: dp to pixels, multiply with display density */
return heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density
}
@CheckResult
fun showKeyboard(viewForInput: View): Completable = if (isKeyboardShown()) {
Completable.complete()
} else {
Completable.fromAction { imm.showSoftInput(viewForInput, 0) }
.concatWith(keyboardReacted(visibility = true))
}
@CheckResult
@JvmOverloads
fun hideKeyboard(view: View = activity.window.decorView): Completable = if (isKeyboardShown()) {
Completable.fromAction { imm.hideSoftInputFromWindow(view.windowToken, 0) }
.concatWith(keyboardReacted(visibility = false))
} else {
Completable.complete()
}
private fun keyboardReacted(visibility: Boolean): Completable = keyboardStates
.first { it == visibility }
.observeOn(mainThread)// Wait when UI reflected (a small delay because of post())
.toCompletable()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment