Bootstrap

QML Listveiw delegate( item ) 不同高度,引起 contentY 不确定问题解决方案

在 QML 开发中 Listview 是经常用的控件,作用过程中发现一个 bug 当每个 delegate 的高度不等的时候,在上下滑动过程中会引起contentY 的变动, 上下来加多滑动几次,加到顶部后 contentY 不再是原来的值了(默认为 0),这时候如果要通过 contentY 做类似下拉刷新的效果就会出问题了。Qt 官方 bug list 说暂时不处理了  https://bugreports.qt.io/browse/QTBUG-31573

经过大量测试,发现 originY 也会随着 contentY  的变化面变化, 最后确认做类似下拉刷新的效果时所有用到 contentY 的地方都用 (contentY - originY)替换就可以了,在Qt 提供的example// qtdeclarative/examples/quick/demos/tweetsearch, 验证过,确实可行,是一种解决办法,现将验证部分代码粘贴如下,提供给各位同学参考,希望同学们斧正:

// qrc:/demos/tweetsearch/tweetsearch.qml // part code
    ListView {
        id: mainListView
        anchors.fill: parent
//        delegate: TweetDelegate { }
//        model: ListModel { id: finalModel }
        model: 200 // for test
        delegate: Item { // for test
            width: parent.width
            height: 40 + Math.random() * 100 // for varying height items
            Rectangle {
                width: parent.width
                height: 1
                color: "#999"
                anchors.bottom: parent.bottom
            }

            Text {
                anchors.centerIn: parent
                text: qsTr("text item %1").arg(index)
            }
        }

        add: Transition {
            NumberAnimation { property: "hm"; from: 0; to: 1.0; duration: 300; easing.type: Easing.OutQuad }
            PropertyAction { property: "appear"; value: 250 }
        }

        onDragEnded: if (header.refresh) { tweetsModel.reload() }

        ListHeader {
            id: header
           // y: -mainListView.contentY - height
           // here use (contentY - originY) replace contentY
            y:(-(mainListView.contentY - mainListView.originY)) - height
        }

//qrc:/demos/tweetsearch/content/ListHeader.qml // part code
    states: [
        State {
            //name: "base"; when: mainListView.contentY >= -120
            // here use (contentY - originY) replace contentY
            name: "base"; when: (mainListView.contentY - mainListView.originY) >= -120
            PropertyChanges { target: arrow; rotation: 180 }
        },
        State {
           // name: "pulled"; when: mainListView.contentY < -120
           // here use (contentY - originY) replace contentY
            name: "pulled"; when: (mainListView.contentY - mainListView.originY) < -120
            PropertyChanges { target: label; text: "Release to refresh..." }
            PropertyChanges { target: arrow; rotation: 0 }
        }
    ]
 

 

;