Skip to content

Commit

Permalink
Fix keyboard disappearing while switching between text fields
Browse files Browse the repository at this point in the history
  • Loading branch information
ASalavei committed Dec 28, 2023
1 parent f9b685a commit 9b22d5d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import androidx.compose.ui.scene.getConstraintsToFillParent
import androidx.compose.ui.unit.Density
import kotlin.math.absoluteValue
import kotlin.math.min
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import org.jetbrains.skia.BreakIterator
import org.jetbrains.skiko.SkikoKey
import org.jetbrains.skiko.SkikoKeyboardEventKind
Expand Down Expand Up @@ -92,6 +94,7 @@ internal class UIKitTextInputService(
* And after clear in updateState function.
*/
private var _tempCursorPos: Int? = null
private val mainScope = MainScope()

override fun startInput(
value: TextFieldValue,
Expand All @@ -106,6 +109,7 @@ internal class UIKitTextInputService(
currentImeOptions = imeOptions
currentImeActionHandler = onImeActionPerformed

textUIView?.removeFromSuperview()
textUIView = IntermediateTextInputUIView(
keyboardEventHandler = keyboardEventHandler,
).also {
Expand All @@ -127,7 +131,13 @@ internal class UIKitTextInputService(
currentImeOptions = null
currentImeActionHandler = null
hideSoftwareKeyboard()
textUIView?.removeFromSuperview()

textUIView?.input = null
textUIView?.let { view ->
mainScope.launch {
view.removeFromSuperview()
}
}
textUIView = null
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package androidx.compose.ui.window

import androidx.compose.ui.util.fastForEachReversed
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import platform.UIKit.UIView

/**
Expand All @@ -43,24 +45,31 @@ internal interface FocusStack<V> {

internal class FocusStackImpl : FocusStack<UIView> {

private var list = emptyList<UIView>()
private var activeViews = emptyList<UIView>()
private var resignedViews = emptyList<UIView>()
private val mainScope = MainScope()

override fun pushAndFocus(view: UIView) {
list += view
activeViews += view
resignedViews -= view
view.becomeFirstResponder()
}

override fun popUntilNext(view: UIView) {
if (list.contains(view)) {
val index = list.indexOf(view)
list.subList(index, list.lastIndex).fastForEachReversed {
it.resignFirstResponder()
if (activeViews.contains(view)) {
val index = activeViews.indexOf(view)
resignedViews += activeViews.subList(index, activeViews.lastIndex)
activeViews = activeViews.subList(0, index)

mainScope.launch {
resignedViews.fastForEachReversed {
it.resignFirstResponder()
}
resignedViews = emptyList()
activeViews.lastOrNull()?.becomeFirstResponder()
}
list = list.subList(0, index)
list.lastOrNull()?.becomeFirstResponder()
}
}

override fun first(): UIView? = list.firstOrNull()

override fun first(): UIView? = activeViews.firstOrNull()
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import platform.Foundation.NSSelectorFromString
import platform.Foundation.dictionary
import platform.UIKit.NSWritingDirection
import platform.UIKit.NSWritingDirectionLeftToRight
import platform.UIKit.UIEvent
import platform.UIKit.UIKeyInputProtocol
import platform.UIKit.UIKeyboardAppearance
import platform.UIKit.UIKeyboardType
Expand Down Expand Up @@ -93,6 +94,14 @@ internal class IntermediateTextInputUIView(
super.pressesEnded(presses, withEvent)
}

override fun hitTest(point: CValue<CGPoint>, withEvent: UIEvent?): UIView? {
return if (input == null) {
null
} else {
super.hitTest(point, withEvent)
}
}

/**
* A Boolean value that indicates whether the text-entry object has any text.
* https://developer.apple.com/documentation/uikit/uikeyinput/1614457-hastext
Expand Down

0 comments on commit 9b22d5d

Please sign in to comment.