Qt QML自定义LIstView

发布于:2025-05-12 ⋅ 阅读:(10) ⋅ 点赞:(0)

QML ListView组合拳做列表,代码不可直接复制使用,需要小改

先上图看效果

· 样式1

wu
三个表格组合成要给,上下滚动时,三个同时滚动,表格2可以左右滚动展示数据,三个表格每一列都可以自定义宽度,列的内容样式(文本、单个按钮、多个按钮、单选框)

· 样式2

在这里插入图片描述
两个表格组合,左侧可以拖动

· 样式3

在这里插入图片描述
正常一个表格,没有组合

原理:

通过三个ListView组合起来,左侧的ListView完全显示,右侧的ListView也完全展示,中间的通过width以及contentWidth实现拖动

操作:

  1. 设置itemWidthDic,通过下标控制每一列的宽度
  2. 设置titleKeyList 给标题赋值
  3. 设置itemTypeDic,控制数据项具体哪一列展示什么样式
  4. 设置itemTitleTypeDic,控制标题具体哪一列展示什么样式
  5. 设置middleItemBeginIndex设置中间列表从哪个下标开始
  6. 设置rightItemBeginIndex设置右侧列表从哪个下标开始。同第四点都设置为0则为效果3。middleItemBeginIndex设置为0,rightItemBeginIndex大于0则为效果2。都设置大于0则为效果1
  7. 设置onXXXXXXXXX信号,则可以监听具体的事件
  8. 重写getIsCheckByCR getTextObjComColor这些函数可以设置具体的数据列
  9. 监听onOnListMoving 对 视野距离进行判断 Math.abs(totalHeight - Math.abs(contentY)) <= viewHeight * 1.5 距离底部小于1.5倍视野时可以继续请求数据等等,实现滚动加载数据
  10. 设置其他项可以控制是否有列的分割线、标题、内容的透明度,标题是否有灰色背景等等

技术点:

  1. 每个控件类型都是Component组件,使用Loader动态加载组件,已Item作为父节点,让Item充满整个列宽度,Item受到外部约束。具体的Button Text 之类的组件作为子节点可以控制样式,因此外部Loader传递给每个组件的参数均一致,具体的组件按需使用
  2. 通过每一个ListViewonContentYChanged,结合!rightData.moving && !leftData.moving 属性,让列表一起滚动时,不会出现中间列表控制其他一起滚动,其他列表又反过来作用中间列表的情况

代码片段:

注意项:代码不可直接粘贴使用,TextObj,CheckButton之类的组件都是封装过的,TextObj封装了Text, CheckButton 则是勾选按钮,需要自己重写样式即可需要改动的都在Component里面,其他的按照自己的需求继续扩写

import QtQuick 2.15
import QtQuick.Controls 2.15
// import QtQuick.Controls 1.4
// import QtGraphicalEffects 1.15
import QtQuick.Layouts 1.15

//暂时只设置左右两个列表,不设置左中右三个列表, 右侧列表完全展示
//2023/04/23日补充左边列表,共左中右三列,左列完全展示,右侧完全展示
Item {
    width: 1184
    height: 444
    // property var totalWidth: 1184
    //当自动设置autoItemWidth,itemWidth失效,minItemWidth始终生效,可以通过设置itemWidthDic指定宽度
    property var itemWidth: 200
    property var minItemWidth: 200
    property var itemWidthDic: ({})
    //列类型
    property var itemTypeDic: ({})
    //标题列类型
    property var itemTitleTypeDic: ({})

    property var autoItemWidth: false
    //两边的边距
    property var leftRightMargin: 24
    //是否显示竖条
    property var needSplitLine: false
    //是否标题灰底
    property var needTitleGrayColor: false
    //标题透明度
    property var titleTextComOpacity: 0.4
    property var contentTextComOpacity: 0.8
    //数据
    property var itemDataList: []
    property var titleKeyList: []
    property var titleKeyReplaceDic: ({})
    //已这个下标开始往后,认定为在右侧列表里面, 设置为0时,左侧列表消失,完全展示右侧列表
    property var rightItemBeginIndex: 0
    //同理上面参数,小于middleItemBeginIndex为左侧,大于等于middleItemBeginIndex,小于rightItemBeginIndex为中间
    property var middleItemBeginIndex: 0
    property alias listViewOfData: rightData
    property var alignDic: ({})
    //信号=============================
    signal onClickButtonObj(var index)
    signal onClick2ButtonObj(var cIndex, var rIndex, var num)
    //当高度发生类似光滑渐变时,派发高度变化的信号(表示列表正在滚动,而不是外界设置高度发生骤变)
    signal onListMoving(var contentY, var totalHeight, var viewHeight)
    signal onClickRadioButtonObj(var cIndex, var rIndex, var isTitle, bool isOn)
    //上滑返回true,下滑返回false
    signal onFlickTopOrBottom(bool isToBottom)
    //================================
    //private
    property var everyKeyWidth: 0
    //列枚举类型类型
    property int rowTextObj: 0
    property int columnRowTextObj: 1
    property int columnRowButton: 2
    property int columnRowRadio: 3
    property int columnRow2Button: 4
    property var keyOfItemType: ({})

    function update()
    {
        keyOfItemType[columnRowTextObj] = textObjCom
        // keyOfItemType[columnRowTextObj] = textObjCom1
        keyOfItemType[columnRowButton] = buttonObjCom
        keyOfItemType[columnRowRadio] = radioBtn
        keyOfItemType[columnRow2Button] = twoButtonObjCom

        let totalKeyCount = 0
        let leftWidth = width - leftRightMargin * 2

        //计算之前去掉已经固定宽度的列表
        for(let i = 0; i < titleKeyList.length; i++)
        {
            if(!itemWidthDic.hasOwnProperty(i))
            {
                totalKeyCount += titleKeyList[i].length
            }
            else
            {
                leftWidth -= itemWidthDic[i]
            }
        }
        console.log("宽度", titleKeyList, totalKeyCount)
        if(totalKeyCount == 0)
        {
            return
        }
        everyKeyWidth = (leftWidth / totalKeyCount).toFixed(2)
        //
        let rightTitleWidth = 0
        let middleTitleWidth = 0
        let leftTitleWidth = 0
        for(let i = 0; i < titleKeyList.length; i++)
        {
            if(i >= rightItemBeginIndex)
            {
                rightTitleWidth += getRowWidthByIndex(i)
            }
            else if(i >= middleItemBeginIndex && i < rightItemBeginIndex)
            {
                middleTitleWidth += getRowWidthByIndex(i)
            }
            else
            {
                leftTitleWidth += getRowWidthByIndex(i)
            }
        }
        rightFilckableItem.width = Math.min(rightTitleWidth, width - leftRightMargin * 2)
        rightFilckableItem.contentWidth = rightTitleWidth
        middleFilckableItem.width = width - leftRightMargin * 2 - rightTitleWidth - leftTitleWidth
        middleFilckableItem.contentWidth = middleTitleWidth
        leftFilckableItem.width = Math.min(leftTitleWidth, width - leftRightMargin * 2)
        leftFilckableItem.contentWidth = leftTitleWidth
        // middleTitle.width = width - leftRightMargin * 2 - rightTitleWidth//middleTitleWidth
        rightTitle.width = rightTitleWidth
        middleTitle.width = middleTitleWidth
        leftTitle.width = leftTitleWidth

        console.log("宽度1", leftWidth, totalKeyCount, rightTitleWidth, middleTitleWidth, titleKeyList.length - rightItemBeginIndex, rightItemBeginIndex, itemDataList.length)
        // rightTitleModel.clear()
        // rightTitleModel.append(new Array(titleKeyList.length - rightItemBeginIndex))
        rightTitle.model = getRightRowCount()
        middleTitle.model = getMiddleRowCount()
        leftTitle.model = getLeftRowCount()

        middleData.model = itemDataList.length
        rightData.model = itemDataList.length
        leftData.model = itemDataList.length

        // tableModel.appendRow({display: "name"})
        // tableModel.appendRow({display: "sex"})
        // tableModel.appendRow({display: "id"})
        // let TableModelColumn
        // console.log(tableView.columns)
        // console.log(tableModel.columnCount())
        // console.log()
        // tableModel.colums
    }

    function getRowWidthByIndex(index)
    {
        if(itemWidthDic.hasOwnProperty(index))
        {
            return itemWidthDic[index]
        }
        if(autoItemWidth == false)
        {
            return itemWidth
        }
        // console.log("计算宽度", index, everyKeyWidth, titleKeyList[index].length, itemWidthDic[index], itemWidth)
        //不是固定宽度,也不是自己设置,通过everyKeyWidth来计算
        return Math.max(everyKeyWidth * titleKeyList[index].length, minItemWidth)
    }

    function getMiddleRowCount()
    {
        return rightItemBeginIndex - middleItemBeginIndex
    }
    function getRightRowCount()
    {
        return titleKeyList.length - rightItemBeginIndex
    }
    function getLeftRowCount()
    {
        return middleItemBeginIndex
    }

    function getDataByColumAndRow(colum, row)
    {
        // console.log("数据个hi", titleKeyList[row], itemDataList[colum], itemDataList[colum][titleKeyList[row]])
        let test = {}
        // if(test.hasOwnProperty())
        let answer = ""
        if(itemDataList[colum] == undefined)
        {
            return ""
        }

        if(itemDataList[colum].hasOwnProperty(titleKeyList[row]))
        {
            answer = itemDataList[colum][titleKeyList[row]]
        }
        else
        {
            answer = itemDataList[colum][row]
        }
        // let returnData = itemDataList[colum][titleKeyList[row]]
        return answer == undefined ? "" : answer
    }

    function getTitleKeyReplaceKey(index, raw = true)
    {
        let key = titleKeyList[index]
        if(raw || !titleKeyReplaceDic.hasOwnProperty(key))
        {
            return key
        }
        return titleKeyReplaceDic[key]
    }

    function getItemTypeByIndex(index)
    {
        if(itemTypeDic.hasOwnProperty(index))
        {
            return keyOfItemType[itemTypeDic[index]]
        }
        return textObjCom
    }

    //标题控件哦~哦!哦~~
    function getTitleTypeByIndex(index)
    {
        if(itemTitleTypeDic.hasOwnProperty(index))
        {
            return keyOfItemType[itemTitleTypeDic[index]]
        }
        return textObjCom
    }

    //==================== 外部可以重写的接口 ================
    //从外部获取的设置项
    function getIsCheckByCR(c, r, isTitle)
    {
        return false
    }

    function getTextObjComColor(c, r, isTitle)
    {
        return "#FFFFFFFF"
    }

    //=====================================================

    function getCurTopShowIndex()
    {
        let mY = middleData.contentY
        let topIndex = Math.ceil(mY / 48)
        return topIndex
    }

    function getCurBottomShowIndex()
    {
        let mY = middleData.contentY + middleData.height
        let topIndex = Math.ceil(mY / 48)
        return topIndex
    }
    //跳转到具体的下标
    function jumpToIndex(index)
    {
        let cY = index * 48
        let newCY = Math.max(0, Math.min(cY, middleData.contentHeight - middleData.height))
        // console.log("硬控???", middleData.contentY, cY, newCY)
        middleData.contentY = newCY
    }
    //删除具体的下标
    function deleteIndex(index)
    {
        itemDataList.splice(index, 1)
        middleData.model = itemDataList.length
        rightData.model = itemDataList.length
        leftData.model = itemDataList.length
    }
    //刷新界面
    function updateListView()
    {
        let middleContentY = middleData.contentY
        middleData.contentY = 0
        rightData.contentY = 0
        leftData.contentY = 0

        middleData.model = 0
        rightData.model = 0
        leftData.model = 0
        middleData.model = itemDataList.length
        rightData.model = itemDataList.length
        leftData.model = itemDataList.length

        middleData.contentY = middleContentY
        rightData.contentY = middleContentY
        leftData.contentY = middleContentY
    }

    Rectangle{
       anchors.fill: parent
       color: "#05FFFFFF"
       radius: 4
       border.width: 2
       border.color: "#1AFFFFFF"

       Rectangle{
           width: parent.width - 4
           anchors.left: parent.left
           anchors.leftMargin: 2
           anchors.top: parent.top
           anchors.topMargin: 50
           height: 2
           color: "#1AFFFFFF"
       }
    }

    Component{
        id: textObjCom
        Item{
            property int rIndex: parent.rIndex != undefined ? parent.rIndex : 0
            property int cIndex: parent.cIndex != undefined ? parent.cIndex : 0
            property real comOpacity: parent.comOpacity != undefined ? parent.comOpacity : 0
            property bool isTitleText: parent.isTitle != undefined ? parent.isTitle : true

            TextObj{
                label: parent.isTitleText ? getTitleKeyReplaceKey(parent.rIndex, false) : getDataByColumAndRow(parent.cIndex, parent.rIndex)
                width: parent.width - 32
                height: parent.height
                anchors.left: parent.left
                anchors.leftMargin: 16
                horizontalAlignment: alignDic.hasOwnProperty(parent.rIndex) ? alignDic[parent.rIndex] : Text.AlignLeft
                maximumLineCount: 2
                color: getTextObjComColor(cIndex, rIndex, isTitle)
                wrapMode: Text.WordWrap
                opacity: parent.comOpacity
            }
        }

    }

    Component{
        id: buttonObjCom

        Item{
            id: buttonObjComItem
            property int rIndex: parent.rIndex != undefined ? parent.rIndex : 0
            property int cIndex: parent.cIndex != undefined ? parent.cIndex : 0
            property real comOpacity: parent.comOpacity != undefined ? parent.comOpacity : 0
            // opacity: 0.2

            Button{
                width: 69
                height: 32

                background: Rectangle{
                    color: "transparent"
                    border.color: "#33FFFFFF"
                    border.width: 2
                    radius: 4
                }

                TextObj{
                    anchors.fill: parent
                    label: "详情"
                }
                // anchors.centerIn: parent
                anchors.right: parent.right
                anchors.rightMargin: 8
                anchors.verticalCenter: parent.verticalCenter

                MouseArea{
                    anchors.fill: parent
                    onClicked: {
                        console.log("点击下标", buttonObjComItem.cIndex)
                        // onClickDetail(buttonObjComItem.cIndex)
                        onClickButtonObj(buttonObjComItem.cIndex)
                    }
                }
            }
        }
    }

    Component{
        id: radioBtn

        Item{
            id: radioBtnComItem
            property int rIndex: parent.rIndex != undefined ? parent.rIndex : 0
            property int cIndex: parent.cIndex != undefined ? parent.cIndex : 0
            property real comOpacity: parent.comOpacity != undefined ? parent.comOpacity : 0
            property bool isTitle: parent.isTitle != undefined ? parent.isTitle : true
            // opacity: 0.2

            CheckButton{
                width: 24
                height: 24

                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.verticalCenter
                checked: getIsCheckByCR(cIndex, rIndex, isTitle)

                onClicked: {
                    onClickRadioButtonObj(cIndex, rIndex, isTitle, isOn)
                }
            }
        }
    }

    Component{
        id: twoButtonObjCom

        Item{
            id: twoButtonObjComItem
            property int rIndex: parent.rIndex != undefined ? parent.rIndex : 0
            property int cIndex: parent.cIndex != undefined ? parent.cIndex : 0
            property real comOpacity: parent.comOpacity != undefined ? parent.comOpacity : 0
            // opacity: 0.2

            ButtonCancel{
                id: button1
                width: 69
                height: 32
                labelTxt: "View"
                // anchors.centerIn: parent
                anchors.right: parent.right
                anchors.rightMargin: (parent.width - (69 + 69 + 16)) / 2
                anchors.verticalCenter: parent.verticalCenter

                onClicked: {
                    onClick2ButtonObj(cIndex, rIndex, 1)
                }
            }

            ButtonCancel{
                id: button2
                width: 69
                height: 32
                labelTxt: "Delete"
                // anchors.centerIn: parent
                anchors.right: button1.left
                anchors.rightMargin: 16
                anchors.verticalCenter: parent.verticalCenter

                onClicked: {
                    onClick2ButtonObj(cIndex, rIndex, 2)
                }
            }
        }
    }
	//右侧阴影条效果
    Rectangle{
        id: markItem
        width: 16
        height: rightFilckableItem.height - 4// - middleTitle.height
        anchors.top: parent.top
        anchors.topMargin: 2
        anchors.right: rightFilckableItem.left
        anchors.rightMargin: 0
        // 定义线性渐变
        gradient: Gradient {
            orientation: Gradient.Horizontal
            // GradientStop { position: 0.0; color: "#2196F3" } // 起始颜色(蓝色)
            // GradientStop { position: 1.0; color: "#4CAF50" } // 结束颜色(绿色)
            GradientStop { position: 0.0; color: "#01000000" } // 起始颜色(蓝色)
            GradientStop { position: 1.0; color: "#1A000000" } // 结束颜色(绿色)
        }
        visible: rightItemBeginIndex > 0
    }

    //右侧东西
    Flickable {
        id: rightFilckableItem
        width: 0
        height: parent.height// - middleTitle.height
        anchors.top: parent.top
        anchors.topMargin: 0
        anchors.right: parent.right
        anchors.rightMargin: leftRightMargin
        contentWidth: 0
        clip: true

        ListView{
            id: rightTitle
            width: 0
            height: 50
            anchors.top: parent.top
            anchors.topMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 0
            orientation: ListView.Horizontal
            clip: true
            model: 0

            delegate: Item{
                property var dataIndex: rightItemBeginIndex + index
                width: getRowWidthByIndex(dataIndex)
                height: rightTitle.height
                Rectangle{
                    anchors.fill: parent
                    color: "#0DFFFFFF"
                    visible: needTitleGrayColor
                }

                Rectangle{
                    width: 2
                    height: parent.height - 2
                    color: "#1AFFFFFF"
                    anchors.left: parent.left
                    anchors.leftMargin: 0
                    anchors.top: parent.top
                    anchors.topMargin: 2
                    visible: needSplitLine && dataIndex != 0
                }

                // 动态加载组件
                Loader {
                    id: loader
                    // 根据模型中的type字段决定加载哪个组件
                    // anchors.fill: parent
                    width: parent.width
                    height: parent.height
                    sourceComponent: getTitleTypeByIndex(dataIndex)
                    // 将模型数据传递给子组件
                    property int rIndex: dataIndex
                    property real comOpacity: titleTextComOpacity
                    property bool isTitle: true
                }
            }
            interactive: false
        }

        ListView{
            id: rightData
            width: rightTitle.width
            height: parent.height - rightTitle.height
            anchors.top: rightTitle.bottom
            anchors.topMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 0
            clip: true
            model: 0

            delegate: Item{
                //行
                property var dataCIndex: index
                width: rightFilckableItem.contentWidth
                height: 48
                ListView{
                    id: rightDataItem
                    width: rightFilckableItem.contentWidth
                    height: 48
                    orientation: ListView.Horizontal
                    clip: true
                    model: getRightRowCount()

                    delegate: Item{
                        property var dataRIndex: rightItemBeginIndex + index
                        width: getRowWidthByIndex(dataRIndex)
                        height: rightDataItem.height

                        Rectangle{
                            width: 2
                            height: parent.height - 2
                            color: "#1AFFFFFF"
                            anchors.left: parent.left
                            anchors.leftMargin: 0
                            anchors.top: parent.top
                            anchors.topMargin: 0
                            visible: needSplitLine && dataRIndex != 0
                        }

                        Loader {
                            id: loader1
                            width: parent.width
                            height: parent.height
                            // 根据模型中的type字段决定加载哪个组件
                            sourceComponent: getItemTypeByIndex(dataRIndex)
                            // 将模型数据传递给子组件
                            property int rIndex: dataRIndex
                            property int cIndex: dataCIndex
                            property real comOpacity: contentTextComOpacity
                            property bool isTitle: false
                        }
                    }

                    interactive: false
                }

                Rectangle{
                    width: parent.width
                    anchors.left: parent.left
                    anchors.leftMargin: 0
                    anchors.bottom: parent.bottom
                    anchors.bottomMargin: 0
                    height: 2
                    color: "#1AFFFFFF"
                }
            }

            onFlickStarted: {
                console.log("##########. " + contentY)
            }

            onFlickEnded: {
                if(verticalVelocity <= 0)
                {
                    onFlickTopOrBottom(true)
                }
                else
                {
                    onFlickTopOrBottom(false)
                }
            }
            onContentYChanged: {
                if (!middleData.moving && !leftData.moving) {
                    middleData.contentY = contentY
                    leftData.contentY = contentY
                }
            }
            // onContentYChanged: {
            //     middleData.contentY = contentY
            // }
        }
    }

    //中间列表
    Flickable {
        id: middleFilckableItem
        width: 0
        height: parent.height// - middleTitle.height
        anchors.top: parent.top
        anchors.topMargin: 0
        anchors.right: rightFilckableItem.left
        anchors.rightMargin: 0
        contentWidth: 0
        clip: true
        boundsBehavior: Flickable.StopAtBounds

        ListView{
            id: middleTitle
            width: 0
            height: 50
            anchors.top: parent.top
            anchors.topMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 0
            orientation: ListView.Horizontal
            clip: true
            model: 0

            delegate: Item{
                property var dataIndex: middleItemBeginIndex + index
                width: getRowWidthByIndex(dataIndex)
                height: rightTitle.height
                Rectangle{
                    anchors.fill: parent
                    color: "#0DFFFFFF"
                    visible: needTitleGrayColor
                }

                Rectangle{
                    width: 2
                    height: parent.height - 2
                    color: "#1AFFFFFF"
                    anchors.left: parent.left
                    anchors.leftMargin: 0
                    anchors.top: parent.top
                    anchors.topMargin: 2
                    visible: needSplitLine && dataIndex != 0
                }
                // 动态加载组件
                Loader {
                    id: loader2
                    width: parent.width
                    height: parent.height
                    sourceComponent: getTitleTypeByIndex(dataIndex)
                    // 将模型数据传递给子组件
                    property int rIndex: dataIndex
                    property real comOpacity: titleTextComOpacity
                    property bool isTitle: true
                }
            }
            interactive: false
        }

        ListView{
            id: middleData
            width: middleTitle.width
            height: parent.height - middleTitle.height
            anchors.top: middleTitle.bottom
            anchors.topMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 0
            clip: true
            model: 0

            delegate: Item{
                //行
                property var dataCIndex: index
                width: middleFilckableItem.contentWidth
                height: 48
                ListView{
                    id: middleDataItem
                    width: middleFilckableItem.contentWidth
                    height: 48
                    orientation: ListView.Horizontal
                    clip: true
                    model: getMiddleRowCount()

                    delegate: Item{
                        property var dataRIndex: middleItemBeginIndex + index
                        width: getRowWidthByIndex(dataRIndex)
                        height: middleDataItem.height

                        Rectangle{
                            width: 2
                            height: parent.height - 2
                            color: "#1AFFFFFF"
                            anchors.left: parent.left
                            anchors.leftMargin: 0
                            anchors.top: parent.top
                            anchors.topMargin: 0
                            visible: needSplitLine && dataRIndex != 0
                        }

                        Loader {
                            id: loader4
                            width: parent.width
                            height: parent.height
                            // 根据模型中的type字段决定加载哪个组件
                            sourceComponent: getItemTypeByIndex(dataRIndex)
                            // 将模型数据传递给子组件
                            property int rIndex: dataRIndex
                            property int cIndex: dataCIndex
                            property real comOpacity: contentTextComOpacity
                            property bool isTitle: false
                        }
                    }

                    interactive: false
                }

                Rectangle{
                    width: parent.width
                    anchors.left: parent.left
                    anchors.leftMargin: 0
                    anchors.bottom: parent.bottom
                    anchors.bottomMargin: 0
                    height: 2
                    color: "#1AFFFFFF"
                }
            }

            onFlickStarted: {
                console.log("##########. " + contentY)
            }

            onMovingChanged: {
                if(moving == false)
                {
                    middleData.listSuddentlyChange = false
                }
            }

            onFlickEnded: {
                if(verticalVelocity <= 0)
                {
                    onFlickTopOrBottom(true)
                }
                else
                {
                    onFlickTopOrBottom(false)
                }
            }
            onContentYChanged: {
                if (!rightData.moving && !leftData.moving) {
                    rightData.contentY = contentY
                    leftData.contentY = contentY
                }
                onListMoving(contentY, contentHeight, height)
                // console.log("高度发生了改变", contentY, contentHeight)
            }

            // onContentYChanged: {
            //     rightData.contentY = contentY
            // }
        }
    }

    //左侧东西
    Flickable {
        id: leftFilckableItem
        width: 0
        height: parent.height// - middleTitle.height
        anchors.top: parent.top
        anchors.topMargin: 0
        anchors.right: middleFilckableItem.left
        anchors.rightMargin: 0
        contentWidth: 0
        clip: true

        ListView{
            id: leftTitle
            width: 0
            height: 50
            anchors.top: parent.top
            anchors.topMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 0
            orientation: ListView.Horizontal
            clip: true
            model: 0

            delegate: Item{
                property var dataIndex: index
                width: getRowWidthByIndex(dataIndex)
                height: rightTitle.height
                Rectangle{
                    anchors.fill: parent
                    color: "#0DFFFFFF"
                    visible: needTitleGrayColor
                }

                Rectangle{
                    width: 2
                    height: parent.height - 2
                    color: "#1AFFFFFF"
                    anchors.left: parent.left
                    anchors.leftMargin: 0
                    anchors.top: parent.top
                    anchors.topMargin: 2
                    visible: needSplitLine && dataIndex != 0
                }
                // 动态加载组件
                Loader {
                    id: leftLoader
                    // 根据模型中的type字段决定加载哪个组件
                    // anchors.fill: parent
                    width: parent.width
                    height: parent.height
                    sourceComponent: getTitleTypeByIndex(dataIndex)
                    // 将模型数据传递给子组件
                    property int rIndex: dataIndex
                    property real comOpacity: titleTextComOpacity
                    property bool isTitle: true
                }
            }
            interactive: false
        }

        ListView{
            id: leftData
            width: leftTitle.width
            height: parent.height - leftTitle.height
            anchors.top: leftTitle.bottom
            anchors.topMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 0
            clip: true
            model: 0

            delegate: Item{
                //行
                property var dataCIndex: index
                width: leftFilckableItem.contentWidth
                height: 48
                ListView{
                    id: leftDataItem
                    width: leftFilckableItem.contentWidth
                    height: 48
                    orientation: ListView.Horizontal
                    clip: true
                    model: getRightRowCount()

                    delegate: Item{
                        property var dataRIndex: index
                        width: getRowWidthByIndex(dataRIndex)
                        height: leftDataItem.height

                        Rectangle{
                            width: 2
                            height: parent.height - 2
                            color: "#1AFFFFFF"
                            anchors.left: parent.left
                            anchors.leftMargin: 0
                            anchors.top: parent.top
                            anchors.topMargin: 0
                            visible: needSplitLine && dataRIndex != 0
                        }

                        Loader {
                            id: loader13
                            width: parent.width
                            height: parent.height
                            // 根据模型中的type字段决定加载哪个组件
                            sourceComponent: getItemTypeByIndex(dataRIndex)
                            // 将模型数据传递给子组件
                            property int rIndex: dataRIndex
                            property int cIndex: dataCIndex
                            property real comOpacity: contentTextComOpacity
                            property bool isTitle: false
                        }
                    }

                    interactive: false
                }

                Rectangle{
                    width: parent.width
                    anchors.left: parent.left
                    anchors.leftMargin: 0
                    anchors.bottom: parent.bottom
                    anchors.bottomMargin: 0
                    height: 2
                    color: "#1AFFFFFF"
                }
            }

            onFlickStarted: {
                console.log("##########. " + contentY)
                // selectListview.contentY = contentY
                // movePos = contentY
            }

            onFlickEnded: {
                if(verticalVelocity <= 0)
                {
                    onFlickTopOrBottom(true)
                }
                else
                {
                    onFlickTopOrBottom(false)
                }
            }
            onContentYChanged: {
                if (!middleData.moving && !rightData.moving) {
                    middleData.contentY = contentY
                    rightData.contentY = contentY
                }
            }
        }
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到