Pull2Reload
Article Metadata
This article show how to reload the content of a ListView by pulling it downward.
Contents |
Background
Given a list we want to let the user reload its content without having a dedicated button.
When the list gets pulled down for more than a certain distance, it should automatically reload its content. An image (usually an arrow) shall appear while the user is pulling down the list and will animate as the reload gets triggered
The functionality has been introduced on other phones and it is now widely adopted for lists whose content changes quite often (e.g. Twitter client, Facebook news feed, etc.).
The example
To show it we'll modify the twitter search client in the examples of QtQuick (twitter) you can find in QTSDK/Examples/4.7/declarative/demos/twitter
The file we will modify is twitter.qml
Timed rotation
The first element to add is a timer to perform the reloading when a pull to reload is detected
Timer {
id: time
interval: 50; running: false; repeat: false
onTriggered: { rssModel.reload(); }
}
All this code does is reloading the model 50ms after being triggered.
Define the header
The most important part of the code is to define a header to be used with the ListView capable of detecting the pull event. The header has to be a Component and it can contain other information for the ListView. In this example it does not contain anything else than the reloading icon.
[...]
Component {
id: listHeader
Item {
width: mainView.width
height: 0
Image {
anchors.bottom: parent.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottomMargin: 10
source: "TwitterCore/images/refresharrow.png"
opacity: -mainView.contentY > 10 ? 1 : 0;
Behavior on opacity { NumberAnimation { duration: 100 } }
rotation: {
var newAngle = - mainView.contentY * 3;
if (newAngle > 180) {
time.start();
return -180;
} else {
newAngle = newAngle > 180 ? 180 : 0;
return -newAngle;
}
}
Behavior on rotation { NumberAnimation { duration: 150 } }
}
}
}
[...]
In the code above please note that:
- the height of the header is 0, so the header itself is normally invisible
- the image is anchored on top of the header, i.e. above the table itself
- the image opacity is set to 0 unless the content of the ListView has been dragged downward, below its normal position
- the image gets rotated by 180 degrees when the content gets dragged for more than a certain amount (in the example 60 points down).
- the rotation is animated to give a proper visual feedback to the user
- when the rotation is triggered the timer defined above ges triggered. This is to give time to the rotation animation to be seen.
Adding the header
The last missing part is to add the header to the ListView. The ListView declaration will then become:
ListView {
id: mainView; model: rssModel.model; delegate: fatDelegate;
width: parent.width; height: parent.height; x: 0; cacheBuffer: 100;
header: listHeader
}
Conclusion
That's it. Now when the user pulls down the table he will see a nice animation with a rotating arrow and the table will be reloaded.


Nice idea and useful. Can you provide a zip file with working code - this appears to omit quite a lot of information like detecting the pull event etc ... adding the zip would help. You could also bling it up a bit with a video and or some screenshots.
Lastly, I think this would be even more useful designed as a reusable component where the user could pass in their own list as a model.
hamishwillee 03:45, 8 March 2011 (UTC)
Hassan kassem -
hamishwillee is right, can you post a zip file please?hassan kassem 09:54, 21 October 2011 (EEST)