ListView.onRemove 动画 vs childrenRect.height

ListView.onRemove animation vs childrenRect.height

当我使用 ListView.onRemove 动画从其模型中删除元素时,我注意到 ListView childrenRect.height 中有奇怪的行为。当我删除除最后一个元素之外的所有元素时,childrenRect.height 属性 是错误的,但是 contentHeight 属性 是可以的。删除 ListView.onRemove 动画结果问题消失了。为什么 childrenRect.height 是错误的?

使用this code你会发现在你移除除最后一个元素之外的所有元素后,你无法在某些区域点击。

import QtQuick 2.0
import QtQuick.Controls 1.0
MouseArea
{
    id: container
    height: 400; width: 600
    Rectangle { id: point; visible: false; width: 6; height: 6; radius: 3; color: "black" }
    onPressed: { point.visible = true; point.x = mouse.x - 3; point.y = mouse.y - 3; }
    ListModel {
        id: listModel
        ListElement { lorem: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, lacinia in, mi. Cras vel lorem." }
        ListElement { lorem: "Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam." }
        ListElement { lorem: "Quisque semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed posuere libero dui id orci." }
        ListElement { lorem: "Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus metus leo non est." }
    }
    ListView {
        id: messageListView
        model: listModel
        anchors.top: container.top; anchors.left: container.left; anchors.right: container.right
        height: childrenRect.height
        onCountChanged: console.log("count: " + count)
        onHeightChanged: console.log("height: " + height) // sometimes wrong
        onContentHeightChanged: console.log("contentHeight: " + contentHeight) // rather ok
        delegate: Item {
            id: messageItem
            anchors.left: parent.left; anchors.right: parent.right
            height: Math.max(50, messageText.height + 12)
            Rectangle { anchors.fill: parent; anchors.margins: 1; opacity: 0.75; color: "green"; radius: 5 }
            Text {
                id: messageText
                anchors.verticalCenter: parent.verticalCenter; anchors.left: parent.left; anchors.right: removeButton.left; anchors.margins: 10
                text: lorem
                color: "white"; horizontalAlignment: Text.AlignHCenter; wrapMode: Text.WordWrap
                font.pixelSize: 16; font.weight: Font.Bold
                style: Text.Outline; styleColor: "black"
                maximumLineCount: 6; elide: Text.ElideRight
            }
            Button {
                id: removeButton
                enabled: (index !== -1) && (messageItem.opacity === 1.0)
                anchors.right: parent.right; anchors.margins: 5
                anchors.verticalCenter: parent.verticalCenter; implicitHeight: 40; implicitWidth: 40
                onClicked: {
                    console.log("remove: " + index);
                    listModel.remove(index);
                }
            }
            ListView.onRemove: SequentialAnimation {
                PropertyAction { target: messageItem; property: "ListView.delayRemove"; value: true }
                /// PROBLEM BEGIN
                NumberAnimation { target: messageItem; properties: "opacity"; from: 1.0; to: 0.0; duration: 500 }
                /// PROBLEM END
                PropertyAction { target: messageItem; property: "ListView.delayRemove"; value: false }
            }
        }
    }
}

因为ListView.childrenRect可能会自己动态改变。例如,尝试在示例代码启动时拖动视图。当所有四个代表从视图顶部消失时,childrenRect.height 增加(即使您注释掉 NumberAnimation)。 这意味着 ListView 将它的 childrenRect 用于内部的某些东西,比如拖动动画,因此这个 属性 对 ListView 用户来说是不可靠的。

使用 contentHeight 而不是 childrenRect.height,这样您总能获得正确的值。或者使用 contentItem.childrenRect.height 根据 Flickable.

做同样的事情