想要显示一个较大块的内容时,而界面无法直接呈现,这时候可选择 Flickable 组件,它就是 Qt Quick 里的可滚动区域。
它有两个基本要点,如何让内容滚起来,以及拖到边界时需要怎样的交互方式。
Flickable 基础用法
将一个超过组件大小的长列表,放进 Flickable 里就能上下滚动:

演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
Flickable {
id: flick
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
contentWidth: width
contentHeight: column.height
Column {
id: column
width: flick.width
spacing: 5
Repeater {
model: 15
Rectangle {
width: flick.width
height: 35
color: index % 2 ? "#e8f4f8" : "#d4eef6"
radius: 3
Text {
anchors.centerIn: parent
text: "列表项 " + (index + 1)
font.pixelSize: 13
}
}
}
}
ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded
}
}
Text {
text: "contentY: " + Math.round(flick.contentY)
font.pointSize: 10
color: "#666"
}
}
}
Flickable 的使用套路很固定,contentWidth 和 contentHeight 必须告诉它内容有多大------这里内容是一列,contentHeight 直接绑 column.height,内容有多高就能滚多远,contentWidth: width 表示横向不超,只做纵向滚动。
接着用 clip: true 把超出视口的内容裁掉,不然会露到外面。滚动条不是自带的,需要自己加进去。
适用场景:长列表、大图浏览、任何内容超出视口的区域。
Flickable 边界行为
左右两个列表对比:左边能拖过头再回弹,右边拖到边界就停住。

演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 10
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "#f9f9f9"
radius: 4
border.color: "#ddd"
Column {
anchors.fill: parent
anchors.margins: 5
spacing: 3
Text {
text: "DragAndOvershootBounds"
font.pixelSize: 9
font.bold: true
color: "#e67e22"
}
Flickable {
id: flick1
width: parent.width
height: parent.height - 18
clip: true
contentWidth: width
contentHeight: col1.height
boundsBehavior: Flickable.DragAndOvershootBounds
Column {
id: col1
width: flick1.width
spacing: 3
Repeater {
model: 12
Rectangle {
width: flick1.width
height: 25
color: index % 2 ? "#ffe0b2" : "#fff3e0"
radius: 2
Text {
anchors.centerIn: parent
text: "项目 " + (index + 1)
font.pixelSize: 10
}
}
}
}
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "#f9f9f9"
radius: 4
border.color: "#ddd"
Column {
anchors.fill: parent
anchors.margins: 5
spacing: 3
Text {
text: "StopAtBounds"
font.pixelSize: 9
font.bold: true
color: "#27ae60"
}
Flickable {
id: flick2
width: parent.width
height: parent.height - 18
clip: true
contentWidth: width
contentHeight: col2.height
boundsBehavior: Flickable.StopAtBounds
Column {
id: col2
width: flick2.width
spacing: 3
Repeater {
model: 12
Rectangle {
width: flick2.width
height: 25
color: index % 2 ? "#c8e6c9" : "#e8f5e9"
radius: 2
Text {
anchors.centerIn: parent
text: "项目 " + (index + 1)
font.pixelSize: 10
}
}
}
}
}
}
}
}
Text {
text: "左侧可拖拽超出边界回弹,右侧到达边界即停止"
font.pointSize: 10
color: "#666"
}
}
}
滚动手感由 boundsBehavior 一个属性决定,取值就这两种:DragAndOvershootBounds 是默认值,拖到边界还能继续拖出去一点,松手自动回弹,移动端列表基本都是这种手感;StopAtBounds 则是一到边界就停,不能越界,桌面工具里更干脆。
两个 Flickable 的核心配置只有一行 boundsBehavior 不同,其余属性完全一样(为了让对比直观,特意给两个列表配了不同的颜色)。
简而言之,想让滚动有弹性,用默认的 DragAndOvershootBounds;想要严格的边界,就写 StopAtBounds。它不影响滚动本身,只决定到边界那一刻的表现。
适用场景:移动端卡片列表(回弹手感)、桌面严格列表(即停)。
已验证环境:
- Qt 版本:Qt 6.8.2、Qt 6.11.1
- 操作系统:Windows 11
- GitHub:QML-Minimal-Demos/qml_flickable_flipable