From 79e06bd4c495a30b8c10c201be04ef5c66d7c30e Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Sun, 25 Oct 2020 02:15:31 +0300 Subject: [PATCH] Tweaked ImagePage behavior This should made reaction to a single tap more reliable and flicking back easier. --- qml/pages/ImagePage.qml | 126 +++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 59 deletions(-) diff --git a/qml/pages/ImagePage.qml b/qml/pages/ImagePage.qml index 2072e0f..2916c32 100644 --- a/qml/pages/ImagePage.qml +++ b/qml/pages/ImagePage.qml @@ -91,11 +91,9 @@ Page { } SilicaFlickable { - id: imageFlickable anchors.fill: parent - clip: true - contentWidth: imagePinchArea.width; - contentHeight: imagePinchArea.height; + flickableDirection: Flickable.VerticalFlick + interactive: !imageOnly PullDownMenu { visible: !imageOnly && imageUrl @@ -107,76 +105,86 @@ Page { } } - transitions: Transition { - NumberAnimation { properties: "contentX, contentY"; easing.type: Easing.Linear } - } - AppNotification { id: imageNotification } - MouseArea { + SilicaFlickable { + id: imageFlickable anchors.fill: parent - visible: singleImage.visible - onClicked: imageOnly = !imageOnly // Toggle "Image only" mode on tap - } + clip: true + contentWidth: imagePinchArea.width + contentHeight: imagePinchArea.height + flickableDirection: Flickable.HorizontalAndVerticalFlick + quickScrollEnabled: false - PinchArea { - id: imagePinchArea - width: Math.max( singleImage.width * singleImage.scale, imageFlickable.width ) - height: Math.max( singleImage.height * singleImage.scale, imageFlickable.height ) + PinchArea { + id: imagePinchArea + width: Math.max( singleImage.width * singleImage.scale, imageFlickable.width ) + height: Math.max( singleImage.height * singleImage.scale, imageFlickable.height ) - enabled: singleImage.visible - pinch { - target: singleImage - minimumScale: 1 - maximumScale: 4 - } + enabled: singleImage.status === Image.Ready + pinch { + target: singleImage + minimumScale: 1 + maximumScale: 4 + } - onPinchUpdated: { - imagePage.centerX = pinch.center.x; - imagePage.centerY = pinch.center.y; - } + onPinchUpdated: { + imagePage.centerX = pinch.center.x + imagePage.centerY = pinch.center.y + imageFlickable.returnToBounds() + } - Image { - id: singleImage - source: imageUrl - width: imagePage.imageWidth * imagePage.sizingFactor - height: imagePage.imageHeight * imagePage.sizingFactor - anchors.centerIn: parent + Image { + id: singleImage + source: imageUrl + width: imagePage.imageWidth * imagePage.sizingFactor + height: imagePage.imageHeight * imagePage.sizingFactor + anchors.centerIn: parent - fillMode: Image.PreserveAspectFit - asynchronous: true + fillMode: Image.PreserveAspectFit + asynchronous: true - visible: status === Image.Ready ? true : false - opacity: status === Image.Ready ? 1 : 0 - Behavior on opacity { NumberAnimation {} } - onScaleChanged: { - var newWidth = singleImage.width * singleImage.scale; - var newHeight = singleImage.height * singleImage.scale; - var oldWidth = singleImage.width * imagePage.previousScale; - var oldHeight = singleImage.height * imagePage.previousScale; - var widthDifference = newWidth - oldWidth; - var heightDifference = newHeight - oldHeight; + visible: opacity > 0 + opacity: status === Image.Ready ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + onScaleChanged: { + var newWidth = singleImage.width * singleImage.scale; + var newHeight = singleImage.height * singleImage.scale; + var oldWidth = singleImage.width * imagePage.previousScale; + var oldHeight = singleImage.height * imagePage.previousScale; + var widthDifference = newWidth - oldWidth; + var heightDifference = newHeight - oldHeight; - if (oldWidth > imageFlickable.width || newWidth > imageFlickable.width) { - var xRatioNew = imagePage.centerX / newWidth; - var xRatioOld = imagePage.centerX / oldHeight; - imageFlickable.contentX = imageFlickable.contentX + ( xRatioNew * widthDifference ); - } - if (oldHeight > imageFlickable.height || newHeight > imageFlickable.height) { - var yRatioNew = imagePage.centerY / newHeight; - var yRatioOld = imagePage.centerY / oldHeight; - imageFlickable.contentY = imageFlickable.contentY + ( yRatioNew * heightDifference ); + if (oldWidth > imageFlickable.width || newWidth > imageFlickable.width) { + var xRatioNew = imagePage.centerX / newWidth; + var xRatioOld = imagePage.centerX / oldHeight; + imageFlickable.contentX = imageFlickable.contentX + ( xRatioNew * widthDifference ); + } + if (oldHeight > imageFlickable.height || newHeight > imageFlickable.height) { + var yRatioNew = imagePage.centerY / newHeight; + var yRatioOld = imagePage.centerY / oldHeight; + imageFlickable.contentY = imageFlickable.contentY + ( yRatioNew * heightDifference ); + } + + imagePage.previousScale = singleImage.scale; + imagePage.oldCenterX = imagePage.centerX; + imagePage.oldCenterY = imagePage.centerY; } + } - imagePage.previousScale = singleImage.scale; - imagePage.oldCenterX = imagePage.centerX; - imagePage.oldCenterY = imagePage.centerY; + MouseArea { + anchors.fill: parent + visible: singleImage.visible + + onClicked: imageOnly = !imageOnly // Toggle "Image only" mode on tap + onDoubleClicked: ; // This introduces a delay before onClicked is invoked } } - } + ScrollDecorator { flickable: imageFlickable } + } } Image { @@ -191,7 +199,7 @@ Page { asynchronous: true fillMode: Image.PreserveAspectFit - opacity: 0.15 + opacity: visible ? 0.15 : 0 + Behavior on opacity { FadeAnimation {} } } - }