ListView Item Manual Positioning Animations QML: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
(Sub-categorize) |
||
(5 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{LangSwitch}} | |||
[[Category:Snippets::QML]] | |||
[[Category:HowTo]] | |||
[[Category:Developing with Qt::Qt Quick::QML]] | |||
==Introduction== | == Introduction == | ||
Let's say for instance instead of wanting a plain ListView with its items laid out horizontally and linearly, you instead want a list to respond so that when one item is selected, that item animates towards a different position (lower y value). This item is singled out and when a different item is selected, they swap places. This was useful for my case of KDE's login manager theme, where the items were user face images. | |||
==Implementation== | == Implementation == | ||
Here we create a ListView, a simple array just as filler for what your model will actually be, a delegate with an image and text item, and then we manually set the y and x position of them. | Here we create a ListView, a simple array just as filler for what your model will actually be, a delegate with an image and text item, and then we manually set the y and x position of them. | ||
== | == QML Code == | ||
<code> | |||
import QtQuick 1.0 | |||
Item { | |||
width: 600 | |||
height: 600 | |||
property int itemWidth: 50 | |||
= | ListView { | ||
id: view | |||
model: new Array(1,2,3,4,5,6,7,8) | |||
delegate: item | |||
anchors { | |||
top: parent.top; | |||
topMargin: 10; | |||
horizontalCenter: | |||
parent.horizontalCenter; | |||
bottom: | |||
parent.bottom; | |||
} | |||
width: model.length * itemWidth + (model.length - 1) * spacing | |||
spacing: 2 | |||
orientation: Qt.Horizontal | |||
snapMode: ListView.SnapOneItem | |||
highlightRangeMode: ListView.ApplyRange | |||
interactive: false | |||
Component.onCompleted: currentIndex = -1; | |||
} | |||
Component { | |||
id: item | |||
Rectangle { | |||
** | width: itemWidth | ||
* | height: 50 | ||
color: "red" | |||
x: { | |||
if (ListView.isCurrentItem) { | |||
if (view.flickingHorizontally) { | |||
(view.width/2)- (width/2) | |||
} else { | |||
(view.width/2)-(width/2) | |||
} | |||
} else { | |||
if ( view.currentIndex==-1) { | |||
index * (width + view.spacing) | |||
} else { | |||
if ( index < view.currentIndex) { | |||
index * (width + view.spacing) + (width/2) | |||
} else { | |||
index * (width + view.spacing)- (width/2) | |||
} | |||
} | |||
} | |||
} | |||
y: ListView.isCurrentItem ? 200 : 0 | |||
Behavior on x { SpringAnimation { spring: 4; damping: 0.4 } } | |||
Behavior on y { SpringAnimation { spring: 4; damping: 0.4 } } | |||
Text { | |||
text: model.index | |||
} | |||
MouseArea { | |||
anchors.fill: parent | |||
onClicked: { | |||
if (!ListView.isCurrentItem) | |||
view.currentIndex = index; | |||
else | |||
view.currentIndex = –1; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
</code> |
Latest revision as of 13:00, 28 November 2016
Introduction
Let's say for instance instead of wanting a plain ListView with its items laid out horizontally and linearly, you instead want a list to respond so that when one item is selected, that item animates towards a different position (lower y value). This item is singled out and when a different item is selected, they swap places. This was useful for my case of KDE's login manager theme, where the items were user face images.
Implementation
Here we create a ListView, a simple array just as filler for what your model will actually be, a delegate with an image and text item, and then we manually set the y and x position of them.
QML Code
import QtQuick 1.0
Item {
width: 600
height: 600
property int itemWidth: 50
ListView {
id: view
model: new Array(1,2,3,4,5,6,7,8)
delegate: item
anchors {
top: parent.top;
topMargin: 10;
horizontalCenter:
parent.horizontalCenter;
bottom:
parent.bottom;
}
width: model.length * itemWidth + (model.length - 1) * spacing
spacing: 2
orientation: Qt.Horizontal
snapMode: ListView.SnapOneItem
highlightRangeMode: ListView.ApplyRange
interactive: false
Component.onCompleted: currentIndex = -1;
}
Component {
id: item
Rectangle {
width: itemWidth
height: 50
color: "red"
x: {
if (ListView.isCurrentItem) {
if (view.flickingHorizontally) {
(view.width/2)- (width/2)
} else {
(view.width/2)-(width/2)
}
} else {
if ( view.currentIndex==-1) {
index * (width + view.spacing)
} else {
if ( index < view.currentIndex) {
index * (width + view.spacing) + (width/2)
} else {
index * (width + view.spacing)- (width/2)
}
}
}
}
y: ListView.isCurrentItem ? 200 : 0
Behavior on x { SpringAnimation { spring: 4; damping: 0.4 } }
Behavior on y { SpringAnimation { spring: 4; damping: 0.4 } }
Text {
text: model.index
}
MouseArea {
anchors.fill: parent
onClicked: {
if (!ListView.isCurrentItem)
view.currentIndex = index;
else
view.currentIndex = –1;
}
}
}
}
}