Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. iOS keyboard doesn't activate when TextField receives focus
Forum Updated to NodeBB v4.3 + New Features

iOS keyboard doesn't activate when TextField receives focus

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
15 Posts 3 Posters 3.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P patrickkidd

    @J.Hilk said in iOS keyboard doesn't activate when TextField receives focus:

    Hi @patrickkidd

    if your QML is inside a QQuickWidget or a QQuickView, than that is a well known, but infixed bug

    https://bugreports.qt.io/browse/QTBUG-63157

    My, very hackish, workaround for iOS is to create an offscreen QLineEdit that I set the focus on manually and forward the textChanged signal to QML.

    I hate it, but it works.

    Do you have a code snippet? How do you detect the QML Item kb focus? Then how do you forward the kb events to the QML component?

    J.HilkJ Offline
    J.HilkJ Offline
    J.Hilk
    Moderators
    wrote on last edited by
    #6

    @patrickkidd
    Ignore the above post.

    I took the time to refine my original fix.

    You can find a working GitHub example here:
    https://github.com/DeiVadder/IosTextFieldWorkaround


    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


    Q: What's that?
    A: It's blue light.
    Q: What does it do?
    A: It turns blue.

    P 1 Reply Last reply
    0
    • J.HilkJ J.Hilk

      @patrickkidd
      Ignore the above post.

      I took the time to refine my original fix.

      You can find a working GitHub example here:
      https://github.com/DeiVadder/IosTextFieldWorkaround

      P Offline
      P Offline
      patrickkidd
      wrote on last edited by
      #7

      @J.Hilk said in iOS keyboard doesn't activate when TextField receives focus:

      @patrickkidd
      Ignore the above post.

      I took the time to refine my original fix.

      You can find a working GitHub example here:
      https://github.com/DeiVadder/IosTextFieldWorkaround

      I tried this concept out in my app and it does work. Of course, there is quite a lot of features that need to be added, for example showing cursor position, allowing the selection of text, things like that.

      Let's hope this bug gets fixed.

      https://alaskafamilysystems.com/

      J.HilkJ 1 Reply Last reply
      0
      • P patrickkidd

        @J.Hilk said in iOS keyboard doesn't activate when TextField receives focus:

        @patrickkidd
        Ignore the above post.

        I took the time to refine my original fix.

        You can find a working GitHub example here:
        https://github.com/DeiVadder/IosTextFieldWorkaround

        I tried this concept out in my app and it does work. Of course, there is quite a lot of features that need to be added, for example showing cursor position, allowing the selection of text, things like that.

        Let's hope this bug gets fixed.

        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #8

        @patrickkidd I think, once the keyboard is up, you could transfer the focus back to the textfield and the keyboard input would actually go to the textfield.

        But I haven't tested that thoroughly


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        P 1 Reply Last reply
        0
        • J.HilkJ J.Hilk

          @patrickkidd I think, once the keyboard is up, you could transfer the focus back to the textfield and the keyboard input would actually go to the textfield.

          But I haven't tested that thoroughly

          P Offline
          P Offline
          patrickkidd
          wrote on last edited by
          #9

          @J.Hilk said in iOS keyboard doesn't activate when TextField receives focus:

          @patrickkidd I think, once the keyboard is up, you could transfer the focus back to the textfield and the keyboard input would actually go to the textfield.

          But I haven't tested that thoroughly

          Negative. Setting focus outside an accepted text input control is the event that hides the iOS keyboard again.

          https://alaskafamilysystems.com/

          J.HilkJ 1 Reply Last reply
          0
          • P patrickkidd

            @J.Hilk said in iOS keyboard doesn't activate when TextField receives focus:

            @patrickkidd I think, once the keyboard is up, you could transfer the focus back to the textfield and the keyboard input would actually go to the textfield.

            But I haven't tested that thoroughly

            Negative. Setting focus outside an accepted text input control is the event that hides the iOS keyboard again.

            J.HilkJ Offline
            J.HilkJ Offline
            J.Hilk
            Moderators
            wrote on last edited by
            #10

            @patrickkidd yes, but textInput is an accepted text input control, just that the keyboard call event isn't forwarded outside the quickwidget.

            Thats at least what I read out of the bug report


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            P 1 Reply Last reply
            0
            • J.HilkJ J.Hilk

              @patrickkidd yes, but textInput is an accepted text input control, just that the keyboard call event isn't forwarded outside the quickwidget.

              Thats at least what I read out of the bug report

              P Offline
              P Offline
              patrickkidd
              wrote on last edited by
              #11

              @J.Hilk said in iOS keyboard doesn't activate when TextField receives focus:

              @patrickkidd yes, but textInput is an accepted text input control, just that the keyboard call event isn't forwarded outside the quickwidget.

              Thats at least what I read out of the bug report

              How exactly would you transfer focus back to the TextField? I tried setting the keyboard focus back to the TextInput item like the following pseudo-snippet and the keyboard was hidden again. Is that what you were thinking about?

              def beginFocus(self, text, textInputQQuickItem):
                  quickWidget = QApplication.focusWidget()
                  lineEdit.setFocus(Qt.MouseFocusReason)
                  quickWidget.setFocus(Qt.MouseFocusReason)
                  textInputQQuickItem.setFocus(True, Qt.MouseFocusReason)
              

              https://alaskafamilysystems.com/

              J.HilkJ 1 Reply Last reply
              0
              • P patrickkidd

                @J.Hilk said in iOS keyboard doesn't activate when TextField receives focus:

                @patrickkidd yes, but textInput is an accepted text input control, just that the keyboard call event isn't forwarded outside the quickwidget.

                Thats at least what I read out of the bug report

                How exactly would you transfer focus back to the TextField? I tried setting the keyboard focus back to the TextInput item like the following pseudo-snippet and the keyboard was hidden again. Is that what you were thinking about?

                def beginFocus(self, text, textInputQQuickItem):
                    quickWidget = QApplication.focusWidget()
                    lineEdit.setFocus(Qt.MouseFocusReason)
                    quickWidget.setFocus(Qt.MouseFocusReason)
                    textInputQQuickItem.setFocus(True, Qt.MouseFocusReason)
                
                J.HilkJ Offline
                J.HilkJ Offline
                J.Hilk
                Moderators
                wrote on last edited by J.Hilk
                #12

                @patrickkidd

                if you take my example and only change the content of IosLineEdit.qml

                to this

                import QtQuick 2.12
                import QtQuick.Controls 2.12
                
                import QLineEdit 1.0
                
                TextInput {
                    id:root
                    onEditingFinished: parent.forceActiveFocus()
                
                    QLineEdit{
                        id:backend
                
                        onTextChanged: root.text = text
                        onEditingFinished: root.parent.forceActiveFocus()
                    }
                
                    MouseArea{
                        anchors.fill: parent
                        visible: Qt.platform.os === "ios" && !root.activeFocus
                
                        onClicked: {
                            backend.init(root.text)
                            shiftFocus.start()
                        }
                
                        Timer{
                            id:shiftFocus
                            interval: 10
                            running: false
                            repeat: false
                            onTriggered: root.forceActiveFocus()
                        }
                    }
                }
                
                

                then the keyboard is called, focus shifted and text input has again all functionality

                have to change my repo I guess ;)


                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                Q: What's that?
                A: It's blue light.
                Q: What does it do?
                A: It turns blue.

                P 2 Replies Last reply
                0
                • J.HilkJ J.Hilk

                  @patrickkidd

                  if you take my example and only change the content of IosLineEdit.qml

                  to this

                  import QtQuick 2.12
                  import QtQuick.Controls 2.12
                  
                  import QLineEdit 1.0
                  
                  TextInput {
                      id:root
                      onEditingFinished: parent.forceActiveFocus()
                  
                      QLineEdit{
                          id:backend
                  
                          onTextChanged: root.text = text
                          onEditingFinished: root.parent.forceActiveFocus()
                      }
                  
                      MouseArea{
                          anchors.fill: parent
                          visible: Qt.platform.os === "ios" && !root.activeFocus
                  
                          onClicked: {
                              backend.init(root.text)
                              shiftFocus.start()
                          }
                  
                          Timer{
                              id:shiftFocus
                              interval: 10
                              running: false
                              repeat: false
                              onTriggered: root.forceActiveFocus()
                          }
                      }
                  }
                  
                  

                  then the keyboard is called, focus shifted and text input has again all functionality

                  have to change my repo I guess ;)

                  P Offline
                  P Offline
                  patrickkidd
                  wrote on last edited by patrickkidd
                  #13

                  @J.Hilk said in iOS keyboard doesn't activate when TextField receives focus:

                  @patrickkidd

                  if you take my example and only change the content of IosLineEdit.qml

                  
                  then the keyboard is called, focus shifted and text input has again all functionality
                  
                  have to change my repo I guess ;)
                  

                  Calling QQuickItem::forceActiveFocus(Qt.MouseFocusReason) still does not help for me in my app. The keyboard does not appear for me in your example using the iOS Simulator either.

                  Below is my own nearly complete drop-in solution that retains focus on the QLineEdit and has extra (and crucial) support for cursor positions and selection areas. It should be all the code you need. Note there is no mouse area, which causes problems in some cases where the TextInput is a child.

                  class LineEditBackEnd(QLineEdit, Debug):
                  
                      def __init__(self, parent):
                          super().__init__(parent)
                          self.setMaximumSize(QSize(0, 0))
                          self.move(-10, -10)
                          self.lower()
                          self.hide()
                  
                      # prevent a seg fault from calling `text` as property from qml                                                                                                                                              
                      @pyqtSlot(result=str)
                      def getText(self):
                          return self.text()
                  
                      @pyqtSlot(str, int, int, int)
                      def beginFocus(self, text, cursorPos, selectionStart, selectionEnd):
                          if self.parent() is None:
                              self.setParent(QApplication.activeWindow())
                          self.blockSignals(True)
                          self.setText(text)
                          self.setCursorPosition(cursorPos)
                          super().setSelection(selectionStart, selectionEnd-selectionStart)
                          self.setFocus(Qt.MouseFocusReason)
                          self.blockSignals(False)
                          self.show()
                          item.forceActiveFocus(Qt.MouseFocusReason)
                  
                      @pyqtSlot(str, int, int)
                      def do_setSelection(self, text, start, end):
                          self.blockSignals(True)
                          if text != self.text():
                              self.setText(text)
                          super().setSelection(start, end-start)
                          self.blockSignals(False)
                  
                      @pyqtSlot(int, int, int)
                      def do_setCursorPosition(self, pos, start, end):
                          self.blockSignals(True)
                          super().setCursorPosition(pos)
                          super().setSelection(start, end-start)
                          self.blockSignals(False)
                  
                      @pyqtSlot(result=int)
                      def getCursorPosition(self):
                          return self.cursorPosition()
                  
                      @pyqtSlot(result=int)
                      def selectionStart(self):
                          return super().selectionStart()
                  
                      @pyqtSlot(result=int)
                      def selectionEnd(self):
                          return super().selectionEnd()
                  
                  qmlRegisterType(LineEditBackEnd, 'LineEditBackEnd', 1, 0, 'LineEditBackEnd')
                  
                  import QtQuick 2.12
                  import QtQuick.Controls 2.5
                  import QtQuick.Layouts 1.12
                  import LineEditBackEnd 1.0
                  
                  // maybe a better text input that actually raises the kb on iOS                                                                                                                                                 
                  
                  TextInput {
                  
                      id: root
                  
                      LineEditBackEnd { id: backend }
                  
                      property bool syncing: false
                      property bool ios: Qt.platform.os == 'ios'
                  
                      onFocusChanged: {
                          if(ios && !syncing) {
                              syncing = true
                              backend.beginFocus(text, cursorPosition, selectionStart, selectionEnd)
                              syncing = false
                          }
                      }
                  
                      onSelectionStartChanged: {
                          if(ios && !syncing) {
                              syncing = true
                              backend.do_setSelection(text, selectionStart, selectionEnd)
                              syncing = false
                          }
                      }
                      onSelectionEndChanged: {
                  	if(ios && !syncing) {
                              syncing = true
                              backend.do_setSelection(text, selectionStart, selectionEnd)
                              syncing = false
                  	}
                      }
                  
                  
                      onCursorPositionChanged: {
                  	if(ios && !syncing) {
                              syncing = true
                              backend.do_setCursorPosition(cursorPosition, selectionStart, selectionEnd)
                              syncing = false
                  	}
                      }
                  
                      Connections {
                  	target: backend
                  
                  	onTextChanged: {
                              if(ios && !syncing) {
                  		syncing = true
                  		root.text = backend.getText()
                  		root.cursorPosition = backend.getCursorPosition()
                                  syncing = false
                              }
                          }
                  
                          onCursorPositionChanged: function(_old, _new) {
                              if(ios && !syncing) {
                                  syncing = true
                                  cursorPosition = _new
                                  syncing = false
                              }
                          }
                          onSelectionChanged: {
                              if(ios && !syncing) {
                                  syncing = true
                                  select(backend.selectionStart(), backend.selectionEnd())
                                  syncing = false
                              }
                          }
                  
                          onEditingFinished: root.parent.forceActiveFocus()
                      }
                  
                  }
                  

                  https://alaskafamilysystems.com/

                  1 Reply Last reply
                  0
                  • J.HilkJ J.Hilk

                    @patrickkidd

                    if you take my example and only change the content of IosLineEdit.qml

                    to this

                    import QtQuick 2.12
                    import QtQuick.Controls 2.12
                    
                    import QLineEdit 1.0
                    
                    TextInput {
                        id:root
                        onEditingFinished: parent.forceActiveFocus()
                    
                        QLineEdit{
                            id:backend
                    
                            onTextChanged: root.text = text
                            onEditingFinished: root.parent.forceActiveFocus()
                        }
                    
                        MouseArea{
                            anchors.fill: parent
                            visible: Qt.platform.os === "ios" && !root.activeFocus
                    
                            onClicked: {
                                backend.init(root.text)
                                shiftFocus.start()
                            }
                    
                            Timer{
                                id:shiftFocus
                                interval: 10
                                running: false
                                repeat: false
                                onTriggered: root.forceActiveFocus()
                            }
                        }
                    }
                    
                    

                    then the keyboard is called, focus shifted and text input has again all functionality

                    have to change my repo I guess ;)

                    P Offline
                    P Offline
                    patrickkidd
                    wrote on last edited by
                    #14

                    @J.Hilk Scratch that, your solution may have better support for cursors and selection areas after all. Could be an error on my end. I'll do some more checking.

                    https://alaskafamilysystems.com/

                    P 1 Reply Last reply
                    0
                    • P patrickkidd

                      @J.Hilk Scratch that, your solution may have better support for cursors and selection areas after all. Could be an error on my end. I'll do some more checking.

                      P Offline
                      P Offline
                      patrickkidd
                      wrote on last edited by patrickkidd
                      #15

                      @patrickkidd said in iOS keyboard doesn't activate when TextField receives focus:

                      @J.Hilk Scratch that, your solution may have better support for cursors and selection areas after all. Could be an error on my end. I'll do some more checking.

                      Hmm, I don't know. I wasn't able to port your solution into my project. The TextInput does not receive text events, or sometimes crashes when setting the text property, and does not support selection behavior. Not sure why. I guess I'll stick with mine which uses the default QtQuick selection behavior, until the Qt bug is fixed.

                      https://alaskafamilysystems.com/

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved