Hi Alberto,
Qt does not provide any info in wheter the pan does occur, nor on the distance panned. Unless your UI does not care about the pan (which is not the case for you), we highly recommend to set https://felgo.com/doc/felgo-nativeutils/#softInputMode-prop to NativeUtils.SoftInputModeAdjustNothing
and handle potential overlaps yourself, by e.g. adjusting the contentY of a Flickable programatically.
Here is an in-depth example of how this could be done:
import Felgo
import QtQuick
App {
id: app
onInitTheme: {
NativeUtils.softInputMode = NativeUtils.SoftInputModeAdjustNothing
}
Navigation {
id: navigation
NavigationItem {
iconType: IconType.home
title: "Test"
NavigationStack {
AppPage {
id: page
title: qsTr("My App")
AppFlickable {
id: flickable
anchors.fill: parent
contentWidth: width
contentHeight: contentWrapper.height
Connections {
target: kbdHelper
enabled: (Theme.isIos || Theme.isAndroid)
function onKbdHeightChanged() {
console.log("kbdHelper.kbdHeight",kbdHelper.kbdHeight)
if(kbdHelper.kbdHeight > 0) {
shiftTimer.start()
} else {
flickable.bottomMargin = 0
}
}
}
Timer {
id: shiftTimer
interval: 25
onTriggered: {
// Calculate distance of flickable to bottom of screen
const bottomDistance = app.height - flickable.mapToItem(null, 0, 0).y - flickable.height
// Add content padding for flickable and shift up flickable if required
flickable.bottomMargin = Math.max(0, kbdHelper.kbdHeight - bottomDistance + kbdHelper.kbdShiftOffset)// - (kaToolBar.visible ? kaToolBar.height : 0)// - (footer ? footer.height : 0)//KATheme.calculateShiftOnKbdShow()
flickable.contentY = flickable.contentY + kbdHelper.calculateShiftOnKbdShow()
}
}
MouseArea {
id: contentWrapper
width: parent.width
height: dp(1000)
onClicked: forceActiveFocus()
Column {
width: parent.width
y: dp(500)
spacing: dp(10)
anchors.horizontalCenter: parent.horizontalCenter
AppTextField {
id: numberField
inputMethodHints: Qt.ImhDigitsOnly
width: parent.width / 2
borderColor: focus ? Theme.tintColor : "black"
borderWidth: 1
anchors.horizontalCenter: parent.horizontalCenter
}
AppTextField {
id: textField
width: parent.width / 2
borderColor: focus ? Theme.tintColor : "black"
borderWidth: 1
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}
}
}
}
// keyboard done helper
Rectangle {
id: keyboardHelperPanel
width: parent.width
height: Qt.inputMethod.keyboardRectangle.height + dp(42)
anchors.bottom: parent.bottom
color: Theme.tabBar.backgroundColor
visible: Qt.platform.os === "ios" && app.keyboardVisible && !Qt.inputMethod.animating
Rectangle {
width: parent.width
height: px(1)
color: Theme.dividerColor
}
AppButton {
id: inputHelperDoneButton
text: qsTr("Done")
anchors.right: parent.right
height: dp(42)
flat: true
fontBold: true
horizontalMargin: 0
verticalMargin: 0
onClicked: page.forceActiveFocus()
}
}
Item {
id: kbdHelper
readonly property bool kbdVisible: Qt.inputMethod.visible
&& (Qt.inputMethod.keyboardRectangle.height > 0 || kbdHelper.kbdHeightAndroid > 0)
&& !Qt.inputMethod.animating
onKbdVisibleChanged: console.log("kbdVisible", kbdVisible)
// Use more accurate keyboard height calculation on Android
// This is required as Qt reports wrong keyboard height for certain keyboards but correct keyboard y value
readonly property int kbdHeightAndroid: app ? app.height - Qt.inputMethod.keyboardRectangle.y : 0
onKbdHeightAndroidChanged: console.log("kbdHeightAndroid", kbdHeightAndroid)
readonly property int kbdHeight: kbdHelper.kbdVisible ? (Qt.platform.os === "ios" ? Qt.inputMethod.keyboardRectangle.height : kbdHelper.kbdHeightAndroid) : 0
//readonly property int kbdHeight: Qt.inputMethod.keyboardRectangle.height // not accurate on Android with certain keyboards
readonly property int kbdY: Qt.inputMethod.keyboardRectangle.y
readonly property int kbdShiftOffset: dp(100)
function calculateShiftOnKbdShow() {
if (kbdHelper.kbdVisible) {
const r = Qt.inputMethod.inputItemClipRectangle
// In some rare cases, Qt returns negative Y value for the inputItemClipRectangle but abs is correct
const rY = Math.abs(r.y)
// If the height is missing, we use a default value, equal to the standard text field
const rHeight = r.height > 0 ? r.height : (app ? app.dp(35) : 35)
if (rHeight + rY > app.height) {
// Situation when keyboard shown, but input rect is not correct, in this case no need to shift.
return 0
}
// If the keyboard covers the input, we calculate the distance to shift it up
// We also add an additional default offset, so it does not directly sit on top of the keyboard
if (rY + rHeight >= kbdHelper.kbdY) {
return rY + rHeight - kbdHelper.kbdY + kbdHelper.kbdShiftOffset
}
}
return 0
}
}
}
Best,
Alex