在下面的例子中,当点击链表项时,链表项都会展开填充整个链表视图
(
ListView
)。
额外的间隔区域被用于添加更多的信息,这种机制使用一个
状态
来
控制
当一个链表项展开时,代理项都能输入
expanded
(展开)状态,在这种状态
下一些属性被改变
需要注意的点:模型、视图、代理:
模型负责产生数据>>
// 链表视图数据来源
ListModel {
id: planets
ListElement {
name: "Picture1"
imageSource: "qrc:/new/preImg/images/a.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture2"
imageSource: "qrc:/new/preImg/images/b.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture3"
imageSource: "qrc:/new/preImg/images/c.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture4"
imageSource: "qrc:/new/preImg/images/d.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture5"
imageSource: "qrc:/new/preImg/images/e.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture6"
imageSource: "qrc:/new/preImg/images/f.jpg"
facts: "there show some comment... "}
}
视图负责组织数据>>
// 链表视图
ListView {
id: listView
anchors.fill: parent
// 设置代理
delegate: detailsDelegate
// 设置数据来源
model: planets
}
这里祖师数据的方式就是 List 方式
代理负责渲染数据>>
// 渲染 Item 的代理
Component {
id: detailsDelegate
Item {
// wrapper 就是链表视图的一项
id: wrapper
// 一个 item 的长和宽
width: listView.width
height: 30
// item 左边显示的文字
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: 30
color: "#FFB6C1"
Text {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 4
font.pixelSize: parent.height-4
color: "white"
// 因为代理被(ListView)告知渲染(ListModel)的数据,
// 所以此代理可以直接访问 ListModel 数据元素的属性
text: name
}
}
// item 右边显示的小图片
Rectangle {
id: image
width: 26
height: 26
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 2
anchors.topMargin: 2
color: "#FFB6C1"
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
// 因为代理被(ListView)告知渲染(ListModel)的数据,
// 所以此代理可以直接访问 ListModel 数据元素的属性
source: imageSource
}
}
// 点击 item 切换到 item 展开状态
MouseArea {
anchors.fill: parent
// 给当前的 item 输入 expanded
onClicked: parent.state = "expanded"
}
// 隐藏说明性文字
Item {
id: factsView
// 将说明性文字隐藏在此 item 的下面,
// 范围是 item.bottom 到 屏幕底部
anchors.top: image.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
// 完全透明
opacity: 0
// 放入文字
Rectangle {
anchors.fill: parent
// 渐变
gradient: Gradient {
GradientStop { position: 0.0; color: "#fed958" }
GradientStop { position: 1.0; color: "#fecc2f" }
}
Text {
anchors.fill: parent
anchors.margins: 5
clip: true
wrapMode: Text.WordWrap
color: "black"
font.pixelSize: 12
// 可以看到,只要是在代理的内部,
// 不论哪里都可以访问到 Model 数据元素的属性
text: facts
}
}
}
// 隐藏关闭按钮
Rectangle {
id: closeButton
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 2
anchors.topMargin: 2
width: 26
height: 26
color: "#DC143C"
// 透明
opacity: 0
MouseArea {
anchors.fill: parent
// 取消 item 的 expanded
onClicked: wrapper.state = ""
}
}
// 展开状态和默认状态之间的切换
// 切换会在展开状态和默认状态之间切换
states: [
State {
// 展开的状态的效果
name: "expanded"
// 当前 item 项布满整个屏幕
PropertyChanges {
target: wrapper
height: listView.height
}
// 将 item 原本右边的小图标布满整个屏幕
PropertyChanges {
target: image
width: listView.width
height: listView.width
anchors.rightMargin: 0
// 预留下30的高度用来显示说明性文字
anchors.topMargin: 30
}
// 本来隐藏的说明性文字让他显示
// 因为说明性文字本来在 item 没展开的时候
// 就隐藏在 item 的下面,这里在 item 的尺寸变大之后
// 取消文字的透明属性
PropertyChanges {
target: factsView
opacity: 1
}
// 关闭按钮从透明到显现
// 本来时候透明按钮隐藏在 item 的右面
PropertyChanges {
target: closeButton
opacity: 1
}
// 隐藏整个 List
// 用户看到的就一个展开之后的 item 布满整个屏幕
PropertyChanges {
target: wrapper.ListView.view
contentY: wrapper.y
// 设置视图的交互为false。
// 这个操作阻止了视图的移动,用户不再能够通过滚动条切换当前项
interactive: false
}
}
]
// item 状态改变的过渡动画
transitions: [
Transition {
NumberAnimation {
duration: 200;
properties: "height,width,anchors.rightMargin,anchors.topMargin,opacity,contentY"
}
}
]
}
}
最重要的就是会写渲染,比如给这一项左边加文字、右边加图片、设置隐藏的文字在 item下边、设置 item 颜色、设置 item 点击动作、设置 item 状态切换、设置 item 状态切换的过渡动画等等!
这是一个数据项,视图将此数据项交给代理之后,代理怎么用数据项的属性,怎么渲染,那属于代理的任务!
完整代码:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 800
title: qsTr("Hello World")
Item {
anchors.fill: parent
// 屏幕背景渐变
Rectangle {
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 0.0; color: "#E6E6FA" }
GradientStop { position: 1.0; color: "#E6E6FA" }
}
}
// 链表视图
ListView {
id: listView
anchors.fill: parent
// 设置代理
delegate: detailsDelegate
// 设置数据来源
model: planets
}
// 链表视图数据来源
ListModel {
id: planets
ListElement {
name: "Picture1"
imageSource: "qrc:/new/preImg/images/a.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture2"
imageSource: "qrc:/new/preImg/images/b.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture3"
imageSource: "qrc:/new/preImg/images/c.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture4"
imageSource: "qrc:/new/preImg/images/d.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture5"
imageSource: "qrc:/new/preImg/images/e.jpg"
facts: "there show some comment... "}
ListElement {
name: "Picture6"
imageSource: "qrc:/new/preImg/images/f.jpg"
facts: "there show some comment... "}
}
// 渲染 Item 的代理
Component {
id: detailsDelegate
Item {
// wrapper 就是链表视图的一项
id: wrapper
// 一个 item 的长和宽
width: listView.width
height: 30
// item 左边显示的文字
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: 30
color: "#FFB6C1"
Text {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 4
font.pixelSize: parent.height-4
color: "white"
// 因为代理被(ListView)告知渲染(ListModel)的数据,
// 所以此代理可以直接访问 ListModel 数据元素的属性
text: name
}
}
// item 右边显示的小图片
Rectangle {
id: image
width: 26
height: 26
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 2
anchors.topMargin: 2
color: "#FFB6C1"
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
// 因为代理被(ListView)告知渲染(ListModel)的数据,
// 所以此代理可以直接访问 ListModel 数据元素的属性
source: imageSource
}
}
// 点击 item 切换到 item 展开状态
MouseArea {
anchors.fill: parent
// 给当前的 item 输入 expanded
onClicked: parent.state = "expanded"
}
// 隐藏说明性文字
Item {
id: factsView
// 将说明性文字隐藏在此 item 的下面,
// 范围是 item.bottom 到 屏幕底部
anchors.top: image.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
// 完全透明
opacity: 0
// 放入文字
Rectangle {
anchors.fill: parent
// 渐变
gradient: Gradient {
GradientStop { position: 0.0; color: "#fed958" }
GradientStop { position: 1.0; color: "#fecc2f" }
}
Text {
anchors.fill: parent
anchors.margins: 5
clip: true
wrapMode: Text.WordWrap
color: "black"
font.pixelSize: 12
// 可以看到,只要是在代理的内部,
// 不论哪里都可以访问到 Model 数据元素的属性
text: facts
}
}
}
// 隐藏关闭按钮
Rectangle {
id: closeButton
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 2
anchors.topMargin: 2
width: 26
height: 26
color: "#DC143C"
// 透明
opacity: 0
MouseArea {
anchors.fill: parent
// 取消 item 的 expanded
onClicked: wrapper.state = ""
}
}
// 展开状态和默认状态之间的切换
// 切换会在展开状态和默认状态之间切换
states: [
State {
// 展开的状态的效果
name: "expanded"
// 当前 item 项布满整个屏幕
PropertyChanges {
target: wrapper
height: listView.height
}
// 将 item 原本右边的小图标布满整个屏幕
PropertyChanges {
target: image
width: listView.width
height: listView.width
anchors.rightMargin: 0
// 预留下30的高度用来显示说明性文字
anchors.topMargin: 30
}
// 本来隐藏的说明性文字让他显示
// 因为说明性文字本来在 item 没展开的时候
// 就隐藏在 item 的下面,这里在 item 的尺寸变大之后
// 取消文字的透明属性
PropertyChanges {
target: factsView
opacity: 1
}
// 关闭按钮从透明到显现
// 本来时候透明按钮隐藏在 item 的右面
PropertyChanges {
target: closeButton
opacity: 1
}
// 隐藏整个 List
// 用户看到的就一个展开之后的 item 布满整个屏幕
PropertyChanges {
target: wrapper.ListView.view
contentY: wrapper.y
// 设置视图的交互为false。
// 这个操作阻止了视图的移动,用户不再能够通过滚动条切换当前项
interactive: false
}
}
]
// item 状态改变的过渡动画
transitions: [
Transition {
NumberAnimation {
duration: 200;
properties: "height,width,anchors.rightMargin,anchors.topMargin,opacity,contentY"
}
}
]
}
}
}
}
运行>>