如何用qml做一个炫酷的二级列表控件ExpandableList

时间:2024-06-01 08:59:13

在日常开发中,我们经常使用二级列表控件,而且我们想做成自定义任何一个样式的,小编亲自做一个这样的控件分享给大家,以后会吧
这个控件格式化成可自定义样式形状的,为了做效果暂时做成定格的二级控件:

如何用qml做一个炫酷的二级列表控件ExpandableList
如何用qml做一个炫酷的二级列表控件ExpandableList
如何用qml做一个炫酷的二级列表控件ExpandableList
好,在这里简单介绍实现这个控件的思路:
首先我们要理解二级控件的构架:

列表视图 父级组件 子级组件 父级数据组 子级数据组
在这里我们通过qml实用的ListModel来存放父级数据和子级数据

import QtQuick 2.5

Item {
    property int pItemHeight:50
    property int cItemHeight:40

    //当前显示子组件的数量
    property int currentChildrenCount:0
    //当前福组件的数量
    property int currentparentcount:appTypemodel.count

    //父组件之间的间隔
    property int parentItemSpacing:20

    //接收对应子控件被点击后返回的引索值,以处理数据的选择
    signal itemClicked(int index);
    id:root

    //子级数据存储
    ListModel{
        id:appsmodel
        ListElement{
            appName:"hellword"
            appType: "media"
        }
        ListElement{
            appName:"tommego music"
            appType: "media"
        }
        ListElement{
            appName:"my ending"
            appType: "media"
        }
        ListElement{
            appName:"close music"
            appType: "media"
        }
        ListElement{
            appName:"tommego media"
            appType: "media"
        }
        ListElement{
            appName:"tommego media"
            appType: "games"
        }
        ListElement{
            appName:"tommego media"
            appType: "games"
        }
        ListElement{
            appName:"tommego media"
            appType: "games"
        }
        ListElement{
            appName:"tommego media"
            appType: "games"
        }

        ListElement{
            appName:"tommego media"
            appType: "games"
        }
        ListElement{
            appName:"tommego media"
            appType: "notes"
        }
        ListElement{
            appName:"tommego media"
            appType: "notes"
        }
        ListElement{
            appName:"tommego media"
            appType: "notes"
        }
        ListElement{
            appName:"tommego media"
            appType: "notes"
        }
        ListElement{
            appName:"tommego media"
            appType: "notes"
        }
        ListElement{
            appName:"tommego media"
            appType: "others"
        }
        ListElement{
            appName:"tommego media"
            appType: "others"
        }
        ListElement{
            appName:"tommego media"
            appType: "others"
        }
        ListElement{
            appName:"tommego media"
            appType: "others"
        }
        ListElement{
            appName:"tommego media"
            appType: "others"
        }
        ListElement{
            appName:"tommego media"
            appType: "others"
        }

    }
    //父级数据存储
    ListModel{
        id:appTypemodel
        ListElement{
            appType: "media"
            shown:false
        }
        ListElement{
            appType: "games"
            shown:false
        }
        ListElement{
            appType: "notes"
            shown:false
        }
        ListElement{
            appType: "others"
            shown:false
        }
    }

    //父级列表显示,内嵌子级列表
    Column{
        id:parentcol
        spacing: parentItemSpacing
        Repeater{
            model:appTypemodel
            delegate:Component{
                id:content

                Item{
                    width: root.width
                    height: appTypemodel.get(parentcontent.cindex).shown?pItemHeight+cItemHeight*appcol.childrenCount:pItemHeight
                    Behavior on height{
                        PropertyAnimation{
                            properties: "height"
                            duration: 350
                            easing.type:Easing.OutQuart
                        }
                    }
                    Rectangle{
                        id:typebnt
                        width: pma.containsMouse?root.width:root.width-20
                        height: pItemHeight
                        radius: pma.containsMouse?0:height/2
                        color: "#3d3c3c"
                        Behavior on radius{
                            PropertyAnimation{
                                properties: "radius"
                                duration: 250
                            }
                        }
                        Behavior on width{
                            PropertyAnimation{
                                properties: "width"
                                duration: 250
                            }
                        }
                        Text {
                            id: typetext
                            text: qsTr(appType)
                            anchors.centerIn: parent
                            color: "#12ccaa"
                            font.pixelSize: 20
                        }
                        MouseArea{
                            id:pma
                            anchors.fill: parent
                            hoverEnabled: true
                            onClicked: {
                                //判断这个父组件是否已经显示子组件
                                if(appTypemodel.get(index).shown==false){
                                    for(var a=0;a<appTypemodel.count;a++){
                                        appTypemodel.setProperty(a,"shown",false)
                                    }
                                    //显示子组件
                                    appTypemodel.setProperty(index,"shown",true)
                                    //告诉root这份子组件的数量,以便更新root的长度
                                    var childrencount=0;
                                    for(var c=0;c<appsmodel.count;c++){
                                        if(appTypemodel.get(parentcontent.cindex).appType==appsmodel.get(c).appType){
                                            childrencount++;
                                        }
                                    }
                                    currentChildrenCount=childrencount
                                }
                                else{
                                    appTypemodel.setProperty(index,"shown",false)
                                }
                            }
                        }
                    }

                    id:parentcontent
                    property int cindex:index

                    //children
                    Column{
                        id:appcol
                        width: root.width
                        clip: true
                        anchors.top:typebnt.bottom
                        property int childrenCount:0
                        height: appTypemodel.get(parentcontent.cindex).shown?cItemHeight*childrenCount:0
                        Behavior on height{
                            PropertyAnimation{
                                properties: "height"
                                duration: 350
                                easing.type: Easing.OutQuart
                            }
                        }

                        Repeater{
                            id:apprep
                            model: ListModel{
                                id:subModel
                                Component.onCompleted: {
                                    for(var c=0;c<appsmodel.count;c++){
                                        if(appTypemodel.get(parentcontent.cindex).appType==appsmodel.get(c).appType){
                                            append({"appName":appsmodel.get(c).appName,
                                                    "appType":appsmodel.get(c).appType,
                                                    "originIndex":c})
                                            /*注意,这里除了存放好了子组件原有的数据还要添加一个originIndex;
                                              *它保存了原来子组件的位置,当按钮选到这个的时候才能返回对应子组件的位置
                                              */
                                        }
                                    }
                                    appcol.childrenCount=subModel.count
                                }
                            }

                            delegate: Rectangle{
                                id:itemconent
                                width: root.width
                                height: cItemHeight
                                color: "#030303"
                                Rectangle{
                                    width: parent.width-20
                                    height: parent.height-10
                                    color: "#331233df"
                                    radius: 5
                                    anchors.centerIn: parent
                                    scale: childrenma.containsMouse?1:0
                                    Behavior on scale{
                                        PropertyAnimation{
                                            properties: "scale"
                                            duration: 350
                                            easing.type: Easing.OutBack
                                        }
                                    }
                                }

                                MouseArea{
                                    id:childrenma
                                    hoverEnabled: true
                                    anchors.fill: parent
                                    onClicked: {
                                        //想root发送点击信号,并且返回子组件的index值
                                        itemClicked(originIndex)
                                    }
                                }
                                Text{
                                    text: qsTr(appName)
                                    anchors.centerIn: parent
                                    color: "#444444"
                                    font.pixelSize: 20
                                    style: Text.Outline
                                    styleColor: "#000000"
                                }
                                Rectangle{
                                    width: parent.width-10
                                    anchors.horizontalCenter: parent.horizontalCenter
                                    height: 2
                                    color: "#000000"
                                    visible: index!=0
                                    Rectangle{
                                        width: parent.width
                                        height: 1
                                        y:1
                                        color: "#222222"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}