diff --git a/navigation/src/main/java/ru/touchin/roboswag/components/navigation/activities/BaseActivity.kt b/navigation/src/main/java/ru/touchin/roboswag/components/navigation/activities/BaseActivity.kt index 316c929..edf3dff 100644 --- a/navigation/src/main/java/ru/touchin/roboswag/components/navigation/activities/BaseActivity.kt +++ b/navigation/src/main/java/ru/touchin/roboswag/components/navigation/activities/BaseActivity.kt @@ -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() + open val keyboardBehaviorDetector: KeyboardBehaviorDetector? = null + init { lifecycle.addObserver(LifecycleLoggingObserver()) } diff --git a/navigation/src/main/java/ru/touchin/roboswag/components/navigation/keyboard_resizeable/KeyboardBehaviorDetector.kt b/navigation/src/main/java/ru/touchin/roboswag/components/navigation/keyboard_resizeable/KeyboardBehaviorDetector.kt new file mode 100644 index 0000000..493c08c --- /dev/null +++ b/navigation/src/main/java/ru/touchin/roboswag/components/navigation/keyboard_resizeable/KeyboardBehaviorDetector.kt @@ -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() + } + } +} diff --git a/navigation/src/main/java/ru/touchin/roboswag/components/navigation/keyboard_resizeable/KeyboardResizeableViewController.kt b/navigation/src/main/java/ru/touchin/roboswag/components/navigation/keyboard_resizeable/KeyboardResizeableViewController.kt new file mode 100644 index 0000000..2d794ac --- /dev/null +++ b/navigation/src/main/java/ru/touchin/roboswag/components/navigation/keyboard_resizeable/KeyboardResizeableViewController.kt @@ -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( + @LayoutRes layoutRes: Int, + creationContext: CreationContext +) : ViewController( + 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() + } + } +}