Merge pull request #225 from TouchInstinct/fix/nested_keyboard_detection
Keyboard detector refactor
This commit is contained in:
commit
4af62593e5
|
|
@ -9,10 +9,12 @@ import ru.touchin.roboswag.components.utils.hideSoftInput
|
|||
import ru.touchin.roboswag.mvi_arch.marker.ViewAction
|
||||
import ru.touchin.roboswag.mvi_arch.marker.ViewState
|
||||
import ru.touchin.roboswag.navigation_base.activities.OnBackPressedListener
|
||||
import ru.touchin.roboswag.navigation_base.keyboard_resizeable.OnHideListener
|
||||
import ru.touchin.roboswag.navigation_base.keyboard_resizeable.OnShowListener
|
||||
|
||||
// CPD-OFF
|
||||
/**
|
||||
* Same code as in [ru.touchin.roboswag.navigation_base.keyboard_resizeable.KeyboardResizeableFragment] but inherited from MviFragment
|
||||
* Same code as in [ru.touchin.roboswag.navigation_base.keyboard_resizeable.StatefulKeyboardResizeableFragment] but inherited from MviFragment
|
||||
* Used to detect IME events (show, hide)
|
||||
*/
|
||||
|
||||
|
|
@ -26,7 +28,7 @@ abstract class MviKeyboardResizableFragment<NavArgs, State, Action, VM>(
|
|||
|
||||
private var isKeyboardVisible: Boolean = false
|
||||
|
||||
private val keyboardHideListener = OnBackPressedListener {
|
||||
private val onBackPressedListener = OnBackPressedListener {
|
||||
if (isKeyboardVisible) {
|
||||
activity.hideSoftInput()
|
||||
true
|
||||
|
|
@ -35,6 +37,18 @@ abstract class MviKeyboardResizableFragment<NavArgs, State, Action, VM>(
|
|||
}
|
||||
}
|
||||
|
||||
private val keyboardHideListener: OnHideListener = {
|
||||
if (isKeyboardVisible) {
|
||||
onKeyboardHide()
|
||||
}
|
||||
isKeyboardVisible = false
|
||||
}
|
||||
|
||||
private val keyboardShowListener: OnShowListener = { diff ->
|
||||
onKeyboardShow(diff)
|
||||
isKeyboardVisible = true
|
||||
}
|
||||
|
||||
private var isHideKeyboardOnBackEnabled = false
|
||||
|
||||
protected open fun onKeyboardShow(diff: Int = 0) {}
|
||||
|
|
@ -54,36 +68,28 @@ abstract class MviKeyboardResizableFragment<NavArgs, State, Action, VM>(
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isHideKeyboardOnBackEnabled) activity.addOnBackPressedListener(keyboardHideListener)
|
||||
if (isHideKeyboardOnBackEnabled) activity.addOnBackPressedListener(onBackPressedListener)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (isKeyboardVisible) activity.hideSoftInput()
|
||||
if (isHideKeyboardOnBackEnabled) activity.removeOnBackPressedListener(keyboardHideListener)
|
||||
if (isHideKeyboardOnBackEnabled) activity.removeOnBackPressedListener(onBackPressedListener)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity.keyboardBehaviorDetector?.apply {
|
||||
keyboardHideListener = {
|
||||
if (isKeyboardVisible) {
|
||||
onKeyboardHide()
|
||||
}
|
||||
isKeyboardVisible = false
|
||||
}
|
||||
keyboardShowListener = { diff ->
|
||||
onKeyboardShow(diff)
|
||||
isKeyboardVisible = true
|
||||
}
|
||||
addOnHideListener(keyboardHideListener)
|
||||
addOnShowListener(keyboardShowListener)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
activity.keyboardBehaviorDetector?.apply {
|
||||
keyboardHideListener = null
|
||||
keyboardShowListener = null
|
||||
removeOnHideListener(keyboardHideListener)
|
||||
removeOnShowListener(keyboardShowListener)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,14 +12,26 @@ import ru.touchin.roboswag.navigation_base.activities.BaseActivity
|
|||
*
|
||||
* Your activity must have android:windowSoftInputMode="adjustResize" at least, otherwise listeners won't be called
|
||||
*/
|
||||
|
||||
typealias OnHideListener = () -> Unit
|
||||
typealias OnShowListener = (Int) -> Unit
|
||||
|
||||
class KeyboardBehaviorDetector(
|
||||
activity: BaseActivity
|
||||
) : LifecycleObserver {
|
||||
|
||||
private val view = activity.window.decorView
|
||||
|
||||
var keyboardHideListener: (() -> Unit)? = null
|
||||
var keyboardShowListener: ((Int) -> Unit)? = null
|
||||
private val keyboardHideListeners: MutableList<OnHideListener> = mutableListOf()
|
||||
private val keyboardShowListeners: MutableList<OnShowListener> = mutableListOf()
|
||||
|
||||
fun addOnHideListener(listener: OnHideListener) { keyboardHideListeners.add(listener) }
|
||||
|
||||
fun addOnShowListener(listener: OnShowListener) { keyboardShowListeners.add(listener) }
|
||||
|
||||
fun removeOnHideListener(listener: OnHideListener) { keyboardHideListeners.remove(listener) }
|
||||
|
||||
fun removeOnShowListener(listener: OnShowListener) { keyboardShowListeners.remove(listener) }
|
||||
|
||||
// -1 when we never measure insets yet
|
||||
var startNavigationBarHeight = -1
|
||||
|
|
@ -27,11 +39,9 @@ class KeyboardBehaviorDetector(
|
|||
|
||||
private val listener = { isKeyboardOpen: Boolean, windowInsets: WindowInsetsCompat ->
|
||||
if (isKeyboardOpen) {
|
||||
keyboardShowListener?.invoke(
|
||||
windowInsets.systemWindowInsetBottom - startNavigationBarHeight
|
||||
)
|
||||
keyboardShowListeners.forEach { it.invoke(windowInsets.systemWindowInsetBottom - startNavigationBarHeight) }
|
||||
} else {
|
||||
keyboardHideListener?.invoke()
|
||||
keyboardHideListeners.forEach { it.invoke()}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,23 @@
|
|||
package ru.touchin.roboswag.navigation_base.keyboard_resizeable
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.View
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import ru.touchin.roboswag.components.utils.hideSoftInput
|
||||
import ru.touchin.roboswag.navigation_base.activities.BaseActivity
|
||||
import ru.touchin.roboswag.navigation_base.activities.OnBackPressedListener
|
||||
import ru.touchin.roboswag.navigation_base.fragments.StatefulFragment
|
||||
import ru.touchin.roboswag.navigation_base.fragments.BaseFragment
|
||||
|
||||
abstract class KeyboardResizeableFragment<TActivity : BaseActivity, TState : Parcelable>(
|
||||
abstract class KeyboardResizeableFragment<TActivity : BaseActivity>(
|
||||
@LayoutRes layoutRes: Int
|
||||
) : StatefulFragment<TActivity, TState>(
|
||||
) : BaseFragment<TActivity>(
|
||||
layoutRes
|
||||
) {
|
||||
|
||||
private var isKeyboardVisible: Boolean = false
|
||||
|
||||
private val keyboardHideListener = OnBackPressedListener {
|
||||
private val onBackPressedListener = OnBackPressedListener {
|
||||
if (isKeyboardVisible) {
|
||||
activity.hideSoftInput()
|
||||
true
|
||||
|
|
@ -28,6 +26,18 @@ abstract class KeyboardResizeableFragment<TActivity : BaseActivity, TState : Par
|
|||
}
|
||||
}
|
||||
|
||||
private val keyboardHideListener: OnHideListener = {
|
||||
if (isKeyboardVisible) {
|
||||
onKeyboardHide()
|
||||
}
|
||||
isKeyboardVisible = false
|
||||
}
|
||||
|
||||
private val keyboardShowListener: OnShowListener = { diff ->
|
||||
onKeyboardShow(diff)
|
||||
isKeyboardVisible = true
|
||||
}
|
||||
|
||||
private var isHideKeyboardOnBackEnabled = false
|
||||
|
||||
protected open fun onKeyboardShow(diff: Int = 0) {}
|
||||
|
|
@ -41,50 +51,35 @@ abstract class KeyboardResizeableFragment<TActivity : BaseActivity, TState : Par
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
|
||||
view.requestApplyInsets()
|
||||
}
|
||||
view.requestApplyInsets()
|
||||
lifecycle.addObserver(activity.keyboardBehaviorDetector as LifecycleObserver)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isHideKeyboardOnBackEnabled) activity.addOnBackPressedListener(keyboardHideListener)
|
||||
if (isHideKeyboardOnBackEnabled) activity.addOnBackPressedListener(onBackPressedListener)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
notifyKeyboardHidden()
|
||||
if (isHideKeyboardOnBackEnabled) activity.removeOnBackPressedListener(keyboardHideListener)
|
||||
if (isKeyboardVisible) activity.hideSoftInput()
|
||||
if (isHideKeyboardOnBackEnabled) activity.removeOnBackPressedListener(onBackPressedListener)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity.keyboardBehaviorDetector?.apply {
|
||||
keyboardHideListener = {
|
||||
if (isKeyboardVisible) {
|
||||
onKeyboardHide()
|
||||
}
|
||||
isKeyboardVisible = false
|
||||
}
|
||||
keyboardShowListener = { diff ->
|
||||
onKeyboardShow(diff)
|
||||
isKeyboardVisible = true
|
||||
}
|
||||
addOnHideListener(keyboardHideListener)
|
||||
addOnShowListener(keyboardShowListener)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
activity.keyboardBehaviorDetector?.apply {
|
||||
keyboardHideListener = null
|
||||
keyboardShowListener = null
|
||||
removeOnHideListener(keyboardHideListener)
|
||||
removeOnShowListener(keyboardShowListener)
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyKeyboardHidden() {
|
||||
if (isKeyboardVisible) onKeyboardHide()
|
||||
isKeyboardVisible = false
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
package ru.touchin.roboswag.navigation_base.keyboard_resizeable
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.View
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import ru.touchin.roboswag.components.utils.hideSoftInput
|
||||
import ru.touchin.roboswag.navigation_base.activities.BaseActivity
|
||||
import ru.touchin.roboswag.navigation_base.activities.OnBackPressedListener
|
||||
import ru.touchin.roboswag.navigation_base.fragments.StatefulFragment
|
||||
|
||||
// CPD-OFF
|
||||
/**
|
||||
* Same code as in [KeyboardResizeableFragment] but inherited from StatefulFragment
|
||||
* Used to detect IME events (show, hide)
|
||||
*/
|
||||
|
||||
abstract class StatefulKeyboardResizeableFragment<TActivity : BaseActivity, TState : Parcelable>(
|
||||
@LayoutRes layoutRes: Int
|
||||
) : StatefulFragment<TActivity, TState>(
|
||||
layoutRes
|
||||
) {
|
||||
|
||||
private var isKeyboardVisible: Boolean = false
|
||||
|
||||
private val onBackPressedListener = OnBackPressedListener {
|
||||
if (isKeyboardVisible) {
|
||||
activity.hideSoftInput()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private val keyboardHideListener: OnHideListener = {
|
||||
if (isKeyboardVisible) {
|
||||
onKeyboardHide()
|
||||
}
|
||||
isKeyboardVisible = false
|
||||
}
|
||||
|
||||
private val keyboardShowListener: OnShowListener = { diff ->
|
||||
onKeyboardShow(diff)
|
||||
isKeyboardVisible = true
|
||||
}
|
||||
|
||||
private var isHideKeyboardOnBackEnabled = false
|
||||
|
||||
protected open fun onKeyboardShow(diff: Int = 0) {}
|
||||
|
||||
protected open fun onKeyboardHide() {}
|
||||
|
||||
protected fun hideKeyboardOnBackPressed() {
|
||||
isHideKeyboardOnBackEnabled = true
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
view.requestApplyInsets()
|
||||
lifecycle.addObserver(activity.keyboardBehaviorDetector as LifecycleObserver)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isHideKeyboardOnBackEnabled) activity.addOnBackPressedListener(onBackPressedListener)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (isKeyboardVisible) activity.hideSoftInput()
|
||||
if (isHideKeyboardOnBackEnabled) activity.removeOnBackPressedListener(onBackPressedListener)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity.keyboardBehaviorDetector?.apply {
|
||||
addOnHideListener(keyboardHideListener)
|
||||
addOnShowListener(keyboardShowListener)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
activity.keyboardBehaviorDetector?.apply {
|
||||
removeOnHideListener(keyboardHideListener)
|
||||
removeOnShowListener(keyboardShowListener)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// CPD-ON
|
||||
Loading…
Reference in New Issue