Reputation: 183
I'm porting an existing QML/C++ application to the Android system. The application is already running on the Android tablet, but I have issues with Android keyboard.
Since my QML/C++ application has implemented its own keyboard, I would like to disable an Android one.
I've tried to add android:windowSoftInputMode="stateAlwaysHidden"
line in AndroidManifest.xml file, but keyboard still appears when I press an edit box.
Since I'm porting an existing application, I do not want to edit the code of application itself. The only things I can edit are AndroidManifest.xml, QtApplication.java and QtActivity.java files. QtApplication
and QtActivity
are derived from Application
and Activity
Android classes.
Is it possible to disable the Android keyboard globally for whole app at the startup of application(with editing manifest file or overriding onCreate
, onStart
or similar functions)?
Are there any functions in Application
and Activity
classes that I can override them and consequently disable native keyboard?
Upvotes: 3
Views: 3178
Reputation: 111
Here is another approach using Qt.inputMethod - hide virtual keyboard immediately when it get visible for example by adding visibleChanged handler in qml root item
Component.onCompleted: {
Qt.inputMethod.visibleChanged.connect(function () {
if (Qt.inputMethod.visible)
Qt.inputMethod.hide()
})
}
With this approach it is also possible to add user interface setting to choose what keyboard to use (system or built in app).
Update:
Have figured out that sometimes there can be a blink of system virtual keyboard before hiding, especially when tapping to text input field to much. Handling visibleChanged in C++ don't solve this issue but seems to make it less frequently.
QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::visibleChanged, [] {
QGuiApplication::inputMethod()->hide();
});
Upvotes: 0
Reputation: 333
QApplication::setAutoSipEnabled(false) disables the software virtual keyboard from popping up automatically. You can use the "Q_OS_ANDROID" preprocessor directive to avoid modifying behavior on your other target platforms:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
#ifdef Q_OS_ANDROID
a.setAutoSipEnabled(false);
#endif
(...)
}
You can programmatically display or hide the virtual keyboard using this code:
QInputMethod* input;
input = QGuiApplication::inputMethod();
if(input->isVisible())
{
input->setVisible(false);
}
else
{
input->setVisible(true);
}
Upvotes: 4
Reputation: 183
After some time I found a solution, actually workaround for this problem. The idea was to consume an event that requests Software Input Panel (QEvent::RequestSoftwareInputPanel
). This event is sent by QML/C++ application to the host Android system.
So, I implemented an event filter called SIPRequestEater.
class SIPRequestEater: public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::RequestSoftwareInputPanel)
{
// filter out RequestSoftwareInputPanel event
return true;
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
};
This filter has to be installed to QCoreApplication
berfore the QCoreApplication::run
is called.
QCoreApplication *coreApp = QCoreApplication::instance();
SIPRequestEater *sipRequestEater = new SIPRequestEater();
coreApp->installEventFilter(sipRequestEater);
It can be installed also on QApllication
.
The problem is, that this filter does not catch QEvent::RequestSoftwareInputPanel
event. My explanation for this is that filters, which are installed with QCoreApplication::installEventFilter(<filter>)
are filters only for input events, from Android to QML application. QEvent::RequestSoftwareInputPanel
is actually going in other direction, from QML application to the Android system. I didn't find out if it is possible to filter/disable output events. Because of this I decided to filter out the focus in event QEvent::FocusIn
which actually causes QEvent::RequestSoftwareInputPanel
.For our application this works as it should. The Android keyboard is not appearing anymore and our edit text fields still get focus, because we have our own implementation of focus and keyboard. I believe that this is not the perfect solution for everyone, that's why I called it workaround.
If someone knows, how to filter out output events, specially QEvent::RequestSoftwareInputPanel
, please post it here.
The final implementation of filter is:
class SIPRequestEater: public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::FocusIn)
{
// filter out FocusIn event
return true;
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
};
Upvotes: 4