I have a custom item that can be scrolled and zoomed in a Qt Quick application. I'm trying to implement the scrolling and zooming using Flickable
and PinchArea
. I need my item to be centered inside the Flickable if its size smaller than the screen size (which is classic behaviour of any gallery app on mobile platforms). Looking here QML FlickArea center content a solution is proposed to center item inside a Flickable. So I implemented this behaviour together with a PinchArea
to allow the user to zoom in with two fingers. Here is a fully working example:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
id: root
visible: true
width: 640
height: 480
title: qsTr("Flickable Image Zoom Example")
Flickable
{
id: flickArea
anchors.fill: parent
focus: true
contentWidth: 800
contentHeight: 1500
clip: true
onFlickStarted: console.debug("Flick started")
Item
{
id: wrapper
width: Math.max(flickArea.width, testRect.width)
height: Math.max(flickArea.height, testRect.height)
PinchArea{
id: pinchArea
property real initialWidth
property real initialHeight
property bool pinching: false
anchors.fill: parent
onPinchStarted: {
console.log("Pinch started")
initialWidth = flickArea.contentWidth
initialHeight = flickArea.contentHeight
pinchArea.pinching = true
}
onPinchUpdated: {
console.log("Pinch updated")
console.debug(pinch.center)
var scaledWidth = pinchArea.initialWidth * pinch.scale
var scaledHeight = pinchArea.initialHeight * pinch.scale
flickArea.contentX += pinch.previousCenter.x - pinch.center.x
flickArea.contentY += pinch.previousCenter.y - pinch.center.y
flickArea.resizeContent(scaledWidth, scaledHeight,
pinch.center)
flickArea.returnToBounds()
onPinchFinished: {
console.log("Pinch finished")
pinchArea.pinching = false
flickArea.returnToBounds()
}
}
// hack needed for flickable to behave
MouseArea{ anchors.fill: parent}
}
Image
{
id: testRect
source: "https://www.applesfromny.com/wp-content/uploads/2020/06/SnapdragonNEW.png"
anchors.centerIn: parent // centered in wrapper
width: flickArea.contentWidth
height: flickArea.contentHeight
}
}
}
}
This works, but there is a problem: when the content size of the flickable is smaller than its width (that is when the image is smaller than the window width or height), the "location" of the pinch behaves strangely and the image no longer zooms at the desired position. When the content size of the flickable is bigger than it width (image occupies the entire screen), the image scales and zooms as expected.