GridView 和 ListView 的使用方式有点像,通过 model 提供数据、delegate 定义每一项的外观、样式。区别在于 GridView 把所有项构建成了一个二维网格,横向、竖向两个方向都可以随意排列。
这篇先用最基础的写法展示 GridView 如何构建二维网格,接着展示 flow、layoutDirection、verticalLayoutDirection 三个方向属性是什么效果。
基础网格
演示代码
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
// 内容卡片
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "#fafafa"
radius: 8
border.color: "#e0e0e0"
border.width: 1
GridView {
id: grid
anchors.fill: parent
anchors.margins: 10
clip: true
cellWidth: 80
cellHeight: 80
model: ListModel {
ListElement { name: "音乐" }
ListElement { name: "电影" }
ListElement { name: "读书" }
ListElement { name: "旅行" }
ListElement { name: "摄影" }
ListElement { name: "编程" }
ListElement { name: "运动" }
ListElement { name: "美食" }
ListElement { name: "游戏" }
ListElement { name: "绘画" }
ListElement { name: "烘焙" }
ListElement { name: "露营" }
}
// delegate 占满整个单元格,内部卡片再留出间距
delegate: Item {
required property int index
required property string name
width: grid.cellWidth
height: grid.cellHeight
Rectangle {
anchors.fill: parent
anchors.margins: 4
radius: 8
color: "#FFFFFF"
border.color: "#e0e0e0"
border.width: 1
Column {
anchors.centerIn: parent
spacing: 4
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: name
color: "#333"
font.pointSize: 12
font.bold: true
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: index + 1
color: "#999"
font.pointSize: 9
}
}
}
}
}
}
// 状态提示
Text {
Layout.fillWidth: true
text: "共 " + grid.count + " 项"
font.pointSize: 10
color: "#666"
}
}
}
格子的大小由 cellWidth 和 cellHeight 决定,delegate 的根元素把宽高直接绑到这两个值上,就等于占满整个格子。
卡片本身另套一层 Rectangle,用 anchors.margins 留出 4px 间隙,相邻两项才不会挤在一起。
model 用 ListModel 描述,每个ListElement定义一个 name 字段,delegate 里用 required property string name 取出来。
index是网格自动给每项编的位置,从0开始,这里加1后显示在名字下面,方便对照顺序。
count是只读属性,直接读就是总项数,底部那行统计就是这么来的。
适用场景:应用宫格入口、兴趣标签墙、图片缩略图总览。
排列方向
同样的网格,用三个开关切换 flow、layoutDirection、verticalLayoutDirection,能拼出好几种排布。
演示代码
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
// 控制条
RowLayout {
Layout.fillWidth: true
spacing: 12
// flow 可选 FlowLeftToRight / FlowTopToBottom
CheckBox {
id: flowCheck
text: "先竖排"
font.pointSize: 10
}
// layoutDirection 可选 LeftToRight / RightToLeft
CheckBox {
id: rtlCheck
text: "水平反向"
font.pointSize: 10
}
// verticalLayoutDirection 可选 TopToBottom / BottomToTop
CheckBox {
id: bottomUpCheck
text: "垂直反向"
font.pointSize: 10
}
Item { Layout.fillWidth: true }
Text {
text: "共 " + grid.count + " 项"
font.pointSize: 10
color: "#666"
}
}
// 内容卡片
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "#fafafa"
radius: 8
border.color: "#e0e0e0"
border.width: 1
GridView {
id: grid
anchors.fill: parent
anchors.margins: 10
clip: true
cellWidth: 70
cellHeight: 60
flow: flowCheck.checked ? GridView.FlowTopToBottom : GridView.FlowLeftToRight
layoutDirection: rtlCheck.checked ? Qt.RightToLeft : Qt.LeftToRight
verticalLayoutDirection: bottomUpCheck.checked ? GridView.BottomToTop : GridView.TopToBottom
model: 40
delegate: Item {
required property int index
width: grid.cellWidth
height: grid.cellHeight
Rectangle {
anchors.fill: parent
anchors.margins: 4
radius: 8
color: "#FFFFFF"
border.color: "#e0e0e0"
border.width: 1
Text {
anchors.centerIn: parent
text: index + 1
color: "#333"
font.pointSize: 12
font.bold: true
}
}
}
}
}
}
}
flow管主方向,GridView.FlowLeftToRight 是默认值,先横着排满一行再换下一行;换成 GridView.FlowTopToBottom 后变成先竖着排满一列再排下一列,滚动方向也跟着从纵向换成横向。
layoutDirection 管水平方向,切到 Qt.RightToLeft 时格子从右边开始摆放;verticalLayoutDirection 管垂直方向,GridView.BottomToTop 让内容从底部往上填。
verticalLayoutDirection有个地方要留意:它只有在内容超过一屏时才看得出来。内容没占满视图的时候BottomToTop 和 TopToBottom 显示得一模一样,所以这个例子把项数放到了 40,专门撑出纵向滚动,勾上「垂直反向」才能看到内容从底部开始排。另外 model 这里直接写了数字 40,是 GridView 的简写方式,表示有 40 项,delegate 里只能拿到 index。
三个方向属性
| 属性 | 控制什么 | 取值 |
|---|---|---|
flow | 先横排还是先竖排 | GridView.FlowLeftToRight / GridView.FlowTopToBottom |
layoutDirection | 水平排列方向 | Qt.LeftToRight / Qt.RightToLeft |
verticalLayoutDirection | 垂直排列方向 | GridView.TopToBottom / GridView.BottomToTop |
已验证环境:
- Qt 版本:Qt 6.12
- 操作系统:Windows 11
- GitHub:QML-Minimal-Demos/qml_gridview