代理(Delegate)
每个代理访问到索引号或者绑定的属性,一些是来自数据模型,一些来自视图。来自模型的数据将会通过属性传递到代理。来自视图的数据将会通过属性传递视图中与代理相关的状态信息。
通常使用的视图绑定属性是ListView.isCurrentItem和ListView.view。第一个是一个布尔值,标识这个元素是否是视图当前元素,这个值是只读的,引用自当前视图。通过访问视图,可以创建可复用的代理,这些代理在被包含时会自动匹配视图的大小。在下面这个例子中,每个代理的width(宽度) 属性与视图的width(宽度) 属性绑定,每个代理的背景颜色color依赖于绑定的属性ListView.isCurrentItem属性。
代码:
import QtQuick 2.0
Rectangle {
width: 120
height: 300
//gradient 梯度,渐变
gradient: Gradient{
GradientStop{position: 0.0; color: "#f6f6f6"}
GradientStop{position: 1.0; color: "#d7d7d7"}
}
ListView{
anchors.fill: parent
anchors.margins: 20
clip: true //可裁剪
model: 100
delegate: numberDelegate
spacing: 5
focus: true
}
//Component 组件
Component{
id:numberDelegate
Rectangle{
width: ListView.view.width
height: 40
color: ListView.isCurrentItem ?"#157efb":"#53d769"
border.color: Qt.lighter(color,1.1)
Text {
anchors.centerIn: parent
font.pixelSize: 10
text: index
}
}
}
}
动画添加与移除元素(Animating Addedand Removed Items)
在某些情况下,视图中的显示内容会随着时间而改变。由于模型数据的改变,元素会添加或者移除。在这些情况下,一个比较好的做法是使用可视化队列给用户一个方向的感觉来帮助用户知道哪些数据被加入或者移除。
为了方便使用,QML视图为每个代理绑定了两个信号,onAdd和onRemove。使用动画连接它们,可以方便创建识别哪些内容被添加或删除的动画。
import QtQuick 2.0
Rectangle {
width: 480
height: 300
gradient: Gradient {
GradientStop { position: 0.0; color: "#dbddde" }
GradientStop { position: 1.0; color: "#5fc9f8" }
}
//初始化列表
ListModel{
id: theModel
ListElement{number:0}
ListElement{number:1}
ListElement{number:2}
ListElement{number:3}
ListElement{number:4}
ListElement{number:5}
ListElement{number:6}
ListElement{number:7}
ListElement{number:8}
ListElement{number:9}
}
//添加按钮
Rectangle
{
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 20
height: 40
color: "#53d769"
border.color: Qt.lighter(color,1.1)
Text {
anchors.centerIn: parent
text: qsTr("add item")
}
MouseArea{
anchors.fill: parent
onClicked: {
theModel.append({"number":++parent.count})
}
}
property int count: 9
}
GridView{
anchors.fill: parent
anchors.margins: 20
anchors.bottomMargin: 80 //为了防止重绘按钮
clip: true
model: theModel
cellHeight: 45
cellWidth: 45
delegate: numberDelegate
}
Component{
id:numberDelegate
Rectangle{
id: wrapper
width: 40
height: 40
gradient: Gradient{
GradientStop{position: 0.0; color: "#f8306a"}
GradientStop{position: 1.0; color: "#fb5b40"}
}
Text {
anchors.centerIn: parent
font.pixelSize: 10
text: number
}
MouseArea{
anchors.fill: parent
onClicked: {
theModel.remove(index)
}
}
GridView.onRemove:SequentialAnimation{
PropertyAction{target:wrapper;property: "GridView.delayRemove";
value: true}
NumberAnimation{target:wrapper; property: "scale";
to: 0; duration: 250; easing.type: Easing.InOutQuad}
PropertyAction { target: wrapper; property: "GridView.delayRemove";
value: false }
}
GridView.onAdd:SequentialAnimation{
NumberAnimation { target: wrapper; property: "scale";
from: 0; to: 1;duration: 250; easing.type: Easing.InOutQuad }
}
}
}
}
在屏幕下方,有一个添加新元素的按钮。当点击它时,会调用模型的append方法来添加一个新的元素。这个操作会触发视图创建一个新的代理,并发送GridView.onAdd信号。SequentialAnimation队列动画与这个信号连接绑定,使用代理的scale属性来放大视图元素。
当视图中的一个代理点击时,将会调用模型的remove方法将一个元素从模型中移除。这个操作将会导致GridView.onRemove信号的发送,触发另一个SequentialAnimation。这时,代理的销毁将会延迟直到动画完成。为了完成这个操作,PropertyAction元素需要在动画前设置GridView.delayRemove属性为true,并在动画后设置为false。这样确保了动画在代理项移除前完成。