這次介紹ListView自身的藝術section屬性,可以達到數據分組顯示的作用,通過設置如下三個屬性:
section.property: "name";
section.criteria: ViewSection.FirstCharacter
section.delegate: sectionHeader
然後實現分組顯示的代理sectionHeader,如下:
Component {
id:sectionHeader
Rectangle {
width: parent.width
height: 20
color: "steelblue"
Label {
text: section
font.bold: true
font.pixelSize: 20
anchors.left: parent.left
anchors.leftMargin: 10
}
}
}
設置了分組的顯示樣式,即可實現通過model中的name字段的首字母進行分組顯示。話不多說先上圖,其初步效果如下:這裏需要注意的是,雖然我們不需要對分組項(上圖中的藍色項)進行管理,但是我們需要對ListModel中要顯示數據進行排序管理,不然會出現多個分組,也就是說,section不會自動排序,相同section的model數據必須放在連續的一塊,不然的話,不連續的section會分別進行顯示,這一點要特別注意(即使這樣,也比以前所有的項全都自己管理強的多^_^)。
實現了以上功能後,還想模仿手機的聯繫人列表,通過右側的字母進行ListView的定位,如下先展示其完整代碼:
import QtQuick 2.5
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.4
import Qt.labs.controls 1.0
import QtQuick.Controls.Styles 1.4
Rectangle {
id: root
width: 800
height: 600
Component {
id:sectionHeader
Rectangle {
width: parent.width
height: 20
color: "steelblue"
Label {
text: section
font.bold: true
font.pixelSize: 20
anchors.left: parent.left
anchors.leftMargin: 10
}
}
}
Rectangle {
width: 200
height: 300
anchors.centerIn: parent
color: "grey"
ListView {
id: list_view
anchors.fill: parent
clip: true
anchors.margins: 5
model: list_model
delegate: Rectangle {
height: 30
width: parent.width
Label {
text: name
anchors.centerIn: parent
color: "green"
}
}
section.property: "name";
section.criteria: ViewSection.FirstCharacter//ViewSection.FullString
section.delegate: sectionHeader
ScrollBar.vertical: ScrollBar {
id: scrollBar
onActiveChanged: {
active = true;
}
Component.onCompleted: {
scrollBar.handle.color = "red";
scrollBar.active = true;
scrollBar.handle.width = 10;
}
}
}
Rectangle {
id: lab
width: 30
height: width
color: "red";
radius: width/2
opacity: 0.8
anchors.centerIn: parent
Label {
id: curLabel
font.pixelSize: 26
font.bold: true
anchors.centerIn: parent
}
visible: false
}
Rectangle {
width: 10
height: parent.height-100
anchors.right: parent.right
anchors.rightMargin: 10
color: "transparent"
anchors.verticalCenter: parent.verticalCenter
Column {
anchors.centerIn: parent
spacing: 3
clip: true
Repeater {
model: ["a","b","c","d","e","f","g","h","i","j","k"]
Label {
text: modelData
font.pixelSize: 16
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
console.log("onClicked:", modelData);
var idx = getIndexFromLab(modelData);
list_view.positionViewAtIndex(idx, ListView.Beginning)
lab.visible = true;
curLabel.text = modelData
}
onExited: lab.visible = false;
}
}
}
}
}
}
function getIndexFromLab(lab)
{
var i;
for (i=0;i<list_model.count;i++)
{
if (list_model.get(i).name.substr(0, 1) === lab)
{
return i;
}
}
return i<=11?i:7;
}
//測試數據
ListModel{
id:list_model
ListElement {
name: "aItem1"
}
ListElement {
name: "aItem2"
}
ListElement {
name: "aItem3"
}
ListElement {
name: "bItem4"
}
ListElement {
name: "bItem5"
}
ListElement {
name: "cItem6"
}
ListElement {
name: "cItem7"
}
ListElement {
name: "tItem8"
}
ListElement {
name: "tItem9"
}
ListElement {
name: "tItem10"
}
ListElement {
name: "wItem11"
}
ListElement {
name: "wItem12"
}
ListElement {
name: "wItem13"
}
ListElement {
name: "zItem14"
}
ListElement {
name: "zItem151"
}
}
}
以上代碼中,不僅實現了model中數據的分組,還通過鼠標滑動到右側的字母上時自動定位ListView的顯示,主要使用了Repeater控件進行分組字母的顯示,通過計算鼠標當前在Repeater中的那個字母上,得出ListView中應該展示的索引(這裏沒有進行詳細的計算,只是初步計算,要想精確定位,在這塊還得繼續優化,請參見下一篇JS遞歸調用定位ListView應該定位的項),然後調用ListView的positionViewAtIndex(idx,
ListView.Beginning)進行顯示的定位,其實現效果如下:如上圖,當鼠標在"c"上時,分組自動定位到C分組,中間的紅圓形顯示當前顯示分組的字母,這樣,完美實現了數據的分組顯示與定位^_^。