目录头尾与填充演示代码高亮跟随演示代码高亮相关属性工程下载GirdView 网格除了中间那些格子首尾还能各挂一块固定内容顶部放统计、底部放「加载更多」都是常见用法。当前选中的那一项也可以交给一个独立的高亮组件来标记而不是写死在 delegate 里。这篇两个例子分别看这两块。头尾与填充顶部是标题加实时计数底部是「加载更多」按钮点一次追加一批加载满后自动变成提示。演示代码import QtQuick import QtQuick.Controls import QtQuick.Layouts FadeInAnimation { id: root property int maxCount: 60 ListModel { id: itemModel // 用循环一次性填充初始数据避免逐条罗列 ListElement Component.onCompleted: { for (var i 1; i 15; i) append({ num: i }) } } 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 model: itemModel cellWidth: 92 cellHeight: 70 cacheBuffer: 500 // 头部分组标题 实时计数 header: Rectangle { width: grid.width height: 44 color: #E8F3FF radius: 8 Text { anchors.left: parent.left anchors.leftMargin: 12 anchors.verticalCenter: parent.verticalCenter text: 全部内容 color: #1296FF font.pointSize: 12 font.bold: true } Text { anchors.right: parent.right anchors.rightMargin: 12 anchors.verticalCenter: parent.verticalCenter text: 共 grid.count 项 color: #1296FF font.pointSize: 11 } } // 尾部加载更多入口加载完切换为提示 footer: Item { width: grid.width height: 52 Button { anchors.centerIn: parent width: 160 font.pointSize: 11 enabled: grid.count root.maxCount text: grid.count root.maxCount ? 加载更多 : 已全部加载 onClicked: { var step Math.min(9, root.maxCount - grid.count) for (var i 0; i step; i) itemModel.append({ num: itemModel.count 1 }) } } } // 新增项的入场动画首次填充与「加载更多」追加的项都走这里 add: Transition { NumberAnimation { properties: x,y; from: -60; duration: 450; easing.type: Easing.OutCubic } NumberAnimation { property: opacity; from: 0; to: 1; duration: 450 } } delegate: Item { required property int num width: grid.cellWidth height: grid.cellHeight Rectangle { anchors.fill: parent anchors.margins: 5 radius: 8 color: #FFFFFF border.color: #e0e0e0 border.width: 1 Text { anchors.centerIn: parent text: num color: #333 font.pointSize: 12 font.bold: true } } } } } Text { Layout.fillWidth: true text: 共 grid.count 项 点击 footer 的按钮追加内容header 的计数会同步变化 font.pointSize: 10 color: #666 } } }header和footer都是Component网格会在首尾各生成一个实例生成出来的对象用只读的headerItem、footerItem就能拿到。header 里左边放标题、右边放项数右边这段文字直接绑grid.count所以追加数据时计数会跟着变。footer 里放了一个按钮点一下用ListModel.append往模型里补 9 项加满 60 项后按钮自动禁用、文案换成「已全部加载」这是「加载更多」的标准写法。网格会把 footer 顶到所有项的后面数据一多它就自然往下走。入场动画交给了add过渡最初填充的 15 项和点「加载更多」追加的那批都属于新加进模型的项统一走这段从左上滑入并淡入的动画。GridView 还有个populate过渡只在视图首次创建或模型被整体替换时播放一次这里是用循环往ListModel里逐条append属于新增路径所以用的是add。适用场景数据列表的分组标题、带「加载更多」的内容流、需要顶部统计的看板。高亮跟随当前项由一块高亮矩形标出来可以在「视图托管」和「自己补间」两种跟随方式之间切换。演示代码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 CheckBox { id: followsCheck checked: true text: 跟随当前项 font.pointSize: 10 } Label { text: 时长 font.pointSize: 10 } SpinBox { id: durBox from: 0 to: 1200 stepSize: 50 value: 150 enabled: followsCheck.checked font.pointSize: 10 Layout.preferredWidth: 84 } Label { text: 范围 font.pointSize: 10 } ComboBox { id: rangeBox font.pointSize: 10 Layout.preferredWidth: 120 model: [不限制, 范围生效, 强制范围] } Item { Layout.fillWidth: true } } // 内容卡片 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 focus: true cellWidth: 84 cellHeight: 84 model: 40 highlightFollowsCurrentItem: followsCheck.checked highlightMoveDuration: durBox.value // NoHighlightRange / ApplyRange / StrictlyEnforceRange highlightRangeMode: rangeBox.currentIndex preferredHighlightBegin: 0 preferredHighlightEnd: grid.cellHeight // 跟随模式切换时高亮实例会被重建 highlight: followsCheck.checked ? managedHighlight : springHighlight delegate: Item { required property int index width: grid.cellWidth height: grid.cellHeight Rectangle { anchors.fill: parent anchors.margins: 5 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 } } MouseArea { anchors.fill: parent onClicked: { grid.currentIndex index grid.forceActiveFocus() } } } } } Text { Layout.fillWidth: true text: 共 %1 项 currentIndex%2 点击或方向键切换.arg(grid.count).arg(grid.currentIndex) font.pointSize: 10 color: #666 elide: Text.ElideRight } } // 交给视图管理几何的高亮 Component { id: managedHighlight Rectangle { color: #1296FF radius: 10 opacity: 0.25 } } // 自行管理几何与移动的高亮 Component { id: springHighlight Rectangle { color: #1296FF radius: 10 opacity: 0.25 width: grid.cellWidth height: grid.cellHeight x: grid.currentItem ? grid.currentItem.x : 0 y: grid.currentItem ? grid.currentItem.y : 0 Behavior on x { SpringAnimation { spring: 3; damping: 0.2 } } Behavior on y { SpringAnimation { spring: 3; damping: 0.2 } } } } }highlight是一个独立于 delegate 的组件视图会负责把它挪到当前项的位置。highlightFollowsCurrentItem为true时这块高亮的尺寸和移动全由视图托管highlightMoveDuration决定移动耗时关掉之后视图不再插手高亮就得自己盯着currentItem走。按开关切两个不同的Component是这里的做法。托管模式下只给颜色和透明度位置宽高交给视图自行跟随模式下把x、y绑到currentItem的坐标上再挂SpringAnimation补间移动时带一点回弹。highlightRangeMode控制当前项是否被限制在视图的某段区间里preferredHighlightBegin和preferredHighlightEnd就是这个区间的起止。选「强制范围」时当前项会被顶到区间位置滚动也跟着它走。适用场景需要明显选中态的宫格、用作选择器或菜单的网格、带键盘导航的图片墙。高亮相关属性属性作用highlight当前项的高亮组件highlightFollowsCurrentItem是否由视图托管高亮的几何与移动highlightMoveDuration视图托管时的移动时长highlightRangeMode当前项是否限制在指定区间内preferredHighlightBegin/preferredHighlightEnd区间的起止位置工程下载我的 Qt 版本Qt 6.12操作系统Windows 11GitHubQML 示例合集V2.0 - qml_gridview