1

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.

reckless
  • 741
  • 12
  • 53

0 Answers0