Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable screen move up in IOS #2595

Closed
nekzabirov opened this issue Jan 3, 2023 · 6 comments
Closed

Disable screen move up in IOS #2595

nekzabirov opened this issue Jan 3, 2023 · 6 comments
Assignees
Labels
ios question Not a bug, but question or comment

Comments

@nekzabirov
Copy link

While the keyboard show my screen move up

How to disable it ?

@dima-avdeev-jb
Copy link
Contributor

This is necessary to correctly display the element in focus. For example, TextField. If the focusable element is in focus and will be covered by the keyboard, then the Compose View will move to keep the element visible.

Screen.Recording.2023-01-09.at.21.11.46.mp4

For now, this behaviour is not configurable.

@dima-avdeev-jb
Copy link
Contributor

@mykytaknyzevkiy
Do you have some bugs with this behaviour?
Can you please provide info on why you need another behaviour?

@dima-avdeev-jb dima-avdeev-jb added question Not a bug, but question or comment wait for reply Further information is requested labels Jan 9, 2023
@nekzabirov
Copy link
Author

nekzabirov commented Jan 12, 2023

@dima-avdeev-jb. I do like to use native IOS UITextField in my Compose view. cause Compose TextField has a lot of bugs.

I found a solution to my problem.

internal val currentRootViewController by lazy {
    ComposeRootController()
}

internal var onKeyboardOpen: ((Boolean) -> Unit)? = null

fun getRootController() = currentRootViewController

class ComposeRootController internal constructor(): UIViewController(null, null) {

    private val keyboardVisibilityListener = object : NSObject() {
        @Suppress("unused")
        @ObjCAction
        fun keyboardWillShow(arg: NSNotification) {
            val (width, height) = getViewFrameSize()

            view.setClipsToBounds(true)

            composeView.layer.setBounds(
                CGRectMake(
                    x = 0.0,
                    y = 0.0,
                    width = width.toDouble(),
                    height = height.toDouble()
                )
            )

            onKeyboardOpen?.invoke(true)
        }

        @Suppress("unused")
        @ObjCAction
        fun keyboardWillHide(arg: NSNotification) {
            val (width, height) = getViewFrameSize()
            view.layer.setBounds(CGRectMake(0.0, 0.0, width.toDouble(), height.toDouble()))

            onKeyboardOpen?.invoke(false)
        }

        @Suppress("unused")
        @ObjCAction
        fun keyboardDidHide(arg: NSNotification) {
            view.setClipsToBounds(false)

            onKeyboardOpen?.invoke(false)

        }
    }

    private val composeView = Application(title = "Nek") {
        App()
    }.view

    override fun viewDidLoad() {
        super.viewDidLoad()

        this.view.addSubview(composeView)
    }

    private fun getViewFrameSize(): IntSize {
        val (width, height) = view.frame().useContents { this.size.width to this.size.height }
        return IntSize(width.toInt(), height.toInt())
    }

    override fun viewDidAppear(animated: Boolean) {
        super.viewDidAppear(animated)
        NSNotificationCenter.defaultCenter.addObserver(
            observer = keyboardVisibilityListener,
            selector = NSSelectorFromString("keyboardWillShow:"),
            name = UIKeyboardWillShowNotification,
            `object` = null
        )

        NSNotificationCenter.defaultCenter.addObserver(
            observer = keyboardVisibilityListener,
            selector = NSSelectorFromString("keyboardWillHide:"),
            name = UIKeyboardWillHideNotification,
            `object` = null
        )
    }
}

@brianguertin
Copy link

The solution provided by @nekzabirov does work. Specifically, after Compose-iOS pans the y upward, we immediately set it back to zero, effectively disabling the built in behavior provide by Compose iOS here:

https://github.com/JetBrains/compose-multiplatform-core/blob/cf7d6a444f4a5dc6379d49de4c8a0867e738a588/compose/ui/ui/src/uikitMain/kotlin/androidx/compose/ui/window/ComposeWindow.uikit.kt#L150

However, sometimes I was seeing a little janky animation from the offset back to 0.0. I was able to fix that by also adding view.layer.removeAllAnimations() when updating the layer bounds.

@brianguertin
Copy link

@dima-avdeev-jb FYI, even with this hacky workaround, Compose iOS does still know how to scroll to the correct view to keep it visible! I was pleasantly surprised that it works exactly as expected now.

@okushnikov
Copy link
Collaborator

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ios question Not a bug, but question or comment
Projects
None yet
Development

No branches or pull requests

5 participants