QML and Android back button

QML and Qt Quick controls allow a very rapid development also mainly for mobile devices. However mobile devices require some additional code for manage special system buttons. In this post we discuss about how to manage the Android back button using QML.


There are many solution to manage Android back button. If not managed correctly the back button pression will close your app immediately and this could be not so good in case your app is in a particular state, like for example a game running. The first and more obvious way is to manage the button pression by intercept the key inside your app. Qt have the Key_Back code and you can manage the key inside QML code in the following way:

Item {
    id: myItem
    focus: true

    Keys.onReleased: {
        if(event.key === Qt.Key_Back) 
        {
            event.accepted = true;
            if(somecondition) 
            {
                .....
            } 
            else 
            { 
                Qt.quit(); 
            }
        }
    }
}

Please, note some important points of this snippet. The first is for allow this code to work correctly the item managing the key need to have the focus set to true. Only one item at a time inside the app can have focus and receive key events. If you have some problem to acquire focus you can force by using the forceActiveFocus() method (in the example is myItem.forceActiveFocus()). The second point to keep in mind is once accepted the key event the event propagation will stop here, this mean the application will never been closed automatically. Once receive the event you have to decide what to do. If you have some special condition to manage (for example a StackView control to switch back) you can do it here. On the contrary if no special condition is present you need to close your app manually by call the quit method. Now this way is the more easy to add but have the problem that a normal app have a lot of controls and this mean focus continuously change based to the action of user. Once the item will lost the focus the code will not work anymore and the back button pression will close the app. I guess is possible to find some trick to keep the focus always on the same item but it doesn't seem a pratical solution at all.

Alternative solution is more safe but require different implementation based to your QML project. The concept is basically the Android back button generate the close event for the app and this is the point to manage. If your QML app is a Window based you can get the onClosing event inside the QML code and use as follow:

ApplicationWindow {
    id: main
    .......
 
    onClosing: {
        if(somecondition)
        {
            close.accepted = false;
            ......
        }
        else
        {
            close.accepted = true;
        }
    }
}

The onClosing event is part of QML Window component, this mean it can be received only on the root of your QML app. In this case the condition request regarding the back button management have to be propagated manually to all the child items eventually "interested" in it. If close.accepted is set to false the close event will be ignored, on the contrary if is ok for you to have the app closed set to true. Now the problem on this code is since you need to use a Window component to get the close event the only way to load the QML code is to use the QQmlApplicationEngine object. If your QML app use the QQuickView or QQuickWindow objects you can not use this solution since these objects doesn't load Window components. In this case the concept is the same but you have to move the trick to the C++ side. Using this alternative you can follow two different ways. The first is to derive the QQuickView or QQuickWindow class and overwrite the keyReleaseEvent(QKeyEvent *e) function. This will allow you to intercept the Key_Back pression event and manage it as required. The second is to connect to the QQuickView or QQuickWindow closing(QQuickCloseEvent *close) signal and manage it in the same way of QML by accepting or refusing the close event. Both solution require to communicate to QML code from C++ side using various ways as explained here.

Comments

Popular posts from this blog

Access GPIO from Linux user space

Launch an app from Android shell terminal

Qt 5 and " Failed to load platform plugin 'windows' " error