add view controller which can detect keyboard opening

This commit is contained in:
Maxim Bachinsky 2019-08-11 14:49:35 +03:00
parent 2296150667
commit 8e08c7a127
3 changed files with 149 additions and 0 deletions

View File

@ -22,6 +22,7 @@ package ru.touchin.roboswag.components.navigation.activities
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import ru.touchin.roboswag.components.navigation.keyboard_resizeable.KeyboardBehaviorDetector
import ru.touchin.roboswag.components.navigation.viewcontrollers.LifecycleLoggingObserver
import ru.touchin.roboswag.core.log.Lc
import ru.touchin.roboswag.core.log.LcGroup
@ -34,6 +35,8 @@ abstract class BaseActivity : AppCompatActivity() {
private val onBackPressedListeners = ArrayList<OnBackPressedListener>()
open val keyboardBehaviorDetector: KeyboardBehaviorDetector? = null
init {
lifecycle.addObserver(LifecycleLoggingObserver())
}

View File

@ -0,0 +1,64 @@
package ru.touchin.roboswag.components.navigation.keyboard_resizeable
import android.graphics.Rect
import android.view.View
import android.view.ViewGroup
import ru.touchin.roboswag.components.navigation.activities.BaseActivity
// The workaround forces an activity to resize when keyboard appears in the full-screen mode
class KeyboardBehaviorDetector(
activity: BaseActivity,
fragmentContainerId: Int
) {
private val contentContainer = activity.findViewById(android.R.id.content) as ViewGroup
private val fragmentContainer = activity.findViewById(fragmentContainerId) as ViewGroup
private lateinit var rootView: View
private val listener = { possiblyResizeChildOfContent() }
private var keyboardHideListener: (() -> Unit)? = null
private var keyboardShowListener: ((Int) -> Unit)? = null
fun setKeyboardHideListener(listener: () -> Unit) {
keyboardHideListener = listener
}
fun removeKeyboardHideListener() {
keyboardHideListener = null
}
fun setKeyboardShowListener(listener: (Int) -> Unit) {
keyboardShowListener = listener
}
fun removeKeyboardShowListener() {
keyboardShowListener = null
}
// Call this in "onResume()" of a fragment
fun startDetection() {
rootView = fragmentContainer.getChildAt(0)
contentContainer.viewTreeObserver.addOnGlobalLayoutListener(listener)
}
// Call this in "onPause()" of a fragment
fun stopDetection() {
contentContainer.viewTreeObserver.removeOnGlobalLayoutListener(listener)
}
//https://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android?rq=1
private fun possiblyResizeChildOfContent() {
val rect = Rect()
rootView.getWindowVisibleDisplayFrame(rect)
val height = rootView.context.resources.displayMetrics.heightPixels
val diff = height - rect.bottom
if (diff > rootView.rootView.height / 4) {
keyboardShowListener?.invoke(diff)
} else {
keyboardHideListener?.invoke()
}
}
}

View File

@ -0,0 +1,82 @@
package ru.touchin.roboswag.components.navigation.keyboard_resizeable
import android.os.Build
import android.os.Parcelable
import androidx.annotation.LayoutRes
import ru.touchin.roboswag.components.navigation.activities.BaseActivity
import ru.touchin.roboswag.components.navigation.activities.OnBackPressedListener
import ru.touchin.roboswag.components.navigation.viewcontrollers.ViewController
import ru.touchin.roboswag.components.utils.UiUtils
abstract class KeyboardResizeableViewController<TActivity : BaseActivity, TState : Parcelable>(
@LayoutRes layoutRes: Int,
creationContext: CreationContext
) : ViewController<TActivity, TState>(
creationContext,
layoutRes
) {
init {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
creationContext.container?.requestApplyInsets()
}
}
private var keyboardIsVisible: Boolean = false
private val keyboardHideListener = OnBackPressedListener {
if (keyboardIsVisible) {
UiUtils.OfViews.hideSoftInput(activity)
true
} else {
false
}
}
private var isHideKeyboardOnBackEnabled = false
protected open fun onKeyboardShow(diff: Int = 0) {}
protected open fun onKeyboardHide() {}
protected fun hideKeyboardOnBackPressed() {
isHideKeyboardOnBackEnabled = true
}
override fun onResume() {
super.onResume()
if (isHideKeyboardOnBackEnabled) activity.addOnBackPressedListener(keyboardHideListener)
}
override fun onPause() {
super.onPause()
if (isHideKeyboardOnBackEnabled) activity.removeOnBackPressedListener(keyboardHideListener)
}
override fun onStart() {
super.onStart()
activity.keyboardBehaviorDetector?.apply {
setKeyboardHideListener {
if (keyboardIsVisible) {
onKeyboardHide()
}
keyboardIsVisible = false
}
setKeyboardShowListener { diff ->
if (!keyboardIsVisible) {
onKeyboardShow(diff)
}
keyboardIsVisible = true
}
startDetection()
}
}
override fun onStop() {
super.onStop()
activity.keyboardBehaviorDetector?.apply {
removeKeyboardHideListener()
removeKeyboardShowListener()
stopDetection()
}
}
}