PDA

View Full Version : Flickable and PinchArea interoperability



sz
10th August 2016, 08:06
Hi all.
It looks like there is a different behavior when using Flickable and PinchArea together, depending on the way we arrange our items in the view.
I tried to use a PinchArea inside a Flickable in order to get a behavior of moving and resizing of an item. The wanted behavior is to apply moving when the user touch only with one finger and, when the user touch with two fingers apply resizing.
That behavior works fine when we put the target item inside the PinchArea, as follows:

// Rectangle inside a PinchArea
Rectangle
{
width: 200; height: 200

Flickable {
id: f1
anchors { fill: parent; margins: 2 }
contentWidth: 300
contentHeight: 300
clip: true
boundsBehavior: Flickable.StopAtBounds

PinchArea {
width: Math.max(f1.contentWidth, f1.width)
height: Math.max(f1.contentHeight, f1.height)

property real initialWidth
property real initialHeight

onPinchStarted: {
initialWidth = f1.contentWidth
initialHeight = f1.contentHeight
}

onPinchUpdated: {
f1.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center)
}

Rectangle {
width: f1.contentWidth
height: f1.contentHeight
color: "white"

RadialGradient
{
anchors.fill: parent
gradient: Gradient{
GradientStop { position: 0.0; color: "blue" }
GradientStop { position: 0.25; color: "cyan" }
GradientStop { position: 0.5; color: "green" }
GradientStop { position: 0.75; color: "red" }
GradientStop { position: 1; color: "orange" }
}
}
}
}
}
}
In the example above it works fine. We can start moving aour item and then resize it when we add another finger.
But, this behavior doesn't work when we put the target item beside the PinchArea, as follows:

// Rectangle beside a PinchArea
Rectangle
{
width: 200; height: 200
x: 200

Flickable {
id: f2
anchors { fill: parent; margins: 2 }
contentWidth: 300
contentHeight: 300
clip: true
boundsBehavior: Flickable.StopAtBounds

Rectangle {
width: f2.contentWidth
height: f2.contentHeight
color: "white"

RadialGradient
{
anchors.fill: parent
gradient: Gradient{
GradientStop { position: 1; color: "blue" }
GradientStop { position: 0.75; color: "cyan" }
GradientStop { position: 0.5; color: "green" }
GradientStop { position: 0.25; color: "red" }
GradientStop { position: 0; color: "orange" }
}
}
}

PinchArea {
width: Math.max(f2.contentWidth, f2.width)
height: Math.max(f2.contentHeight, f2.height)

property real initialWidth
property real initialHeight

onPinchStarted: {
initialWidth = f2.contentWidth
initialHeight = f2.contentHeight
}

onPinchUpdated: {
f2.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center)
}
}
}
}
When we put the target item beside the PinchArea we can resize the item (using the PinchArea) but, once we start moving a finger on the item, the Flickable steals all the touch events and the resizing (using the PinchArea) isn't applied.

Can anyone explain the difference of the behavior (between using an item inside or beside a PinchArea)?
Is there a way to make the wanted behavior (to apply moving when the user touch only with one finger and, when the user touch with two fingers apply resizing) to work also when we put the target item beside the PinchArea?

sz
10th August 2016, 14:03
I found a solution. If we put an item inside the pinch area (in addition to the target item that is beside the PinchArea), it works with the wanted behavior. For let it work I just put a transparent Rectangle inside the PinchArea, as follows:

// Rectangle beside a PinchArea
Rectangle
{
width: 200; height: 200
x: 200

Flickable {
id: f2
anchors { fill: parent; margins: 2 }
contentWidth: 300
contentHeight: 300
clip: true
boundsBehavior: Flickable.StopAtBounds

Rectangle {
width: f2.contentWidth
height: f2.contentHeight
color: "white"

RadialGradient
{
anchors.fill: parent
gradient: Gradient{
GradientStop { position: 1; color: "blue" }
GradientStop { position: 0.75; color: "cyan" }
GradientStop { position: 0.5; color: "green" }
GradientStop { position: 0.25; color: "red" }
GradientStop { position: 0; color: "orange" }
}
}
}

PinchArea {
width: Math.max(f2.contentWidth, f2.width)
height: Math.max(f2.contentHeight, f2.height)

property real initialWidth
property real initialHeight

onPinchStarted: {
initialWidth = f2.contentWidth
initialHeight = f2.contentHeight
}

onPinchUpdated: {
f2.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center)
}

Rectangle {
anchors.fill: parent
color: "transparent"
}
}
}
}

So, now it works. But, it still weird way we have to put an item inside a PinchArea, in order to make it work properly inside a Flickable.