QML中ListView数据的分组与定位显示

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Shado_walker/article/details/61202539
在QML中ListView的数据分组与定位显示时,以前使用ListView进行数据分组时,都是在model中加入分组数据(分组的项),然后将model中的数据排好序后全部显示到ListView中,这样做也能达到数据分组的目的,但是数据维护太费力,我们自己好做的事情太多,埋下的隐藏问题也就越多。
这次介绍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分组,中间的红圆形显示当前显示分组的字母,这样,完美实现了数据的分组显示与定位^_^。


猜你喜欢

转载自blog.csdn.net/Shado_walker/article/details/61202539