带部分的 ListView,删除动画不适用于顶部项目

Posted

技术标签:

【中文标题】带部分的 ListView,删除动画不适用于顶部项目【英文标题】:ListView with section, Remove Animation not working for the top item 【发布时间】:2020-08-02 16:01:50 【问题描述】:

我正在使用带有部分的 QML ListView,单击要删除动画的项目。代码如下:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window 
    visible: true
    width: 400
    height: 400

    ListView 
        id: list
        anchors.fill: parent
        clip: true
        spacing: 0

        onContentYChanged: console.log("onContentYChanged: " + contentY)
        onContentHeightChanged: console.log("onContentHeightChanged: " + contentHeight)

        model: ListModel 
            id: myModel
            ListElement name: "Item 1";type: "A"
            ListElement name: "Item 2";type: "A"
            ListElement name: "Item 3";type: "B"
        

        delegate: Rectangle 
            width: parent.width
            height: 50
            color: (index % 2 == 1) ? "#5678a2" : "#88a345"

            Text 
                anchors.verticalCenter: parent.verticalCenter
                text: name
            

            MouseArea 
                anchors.fill: parent
                onClicked: 
                    console.log("remove: " + index + ", contentY:" + list.contentY)
                    myModel.remove(index)
                
            
        

        section.property: "type"
        section.delegate: Rectangle 
            height: 30
            Text 
                anchors.verticalCenter: parent.verticalCenter
                text: section
            
        

        displaced: Transition 
            NumberAnimation  properties: "x,y"; duration: 500; easing.type: Easing.OutCubic 
        
        remove: Transition 
            NumberAnimation  property: "opacity"; from: 1.0; to: 0; duration: 500 
            NumberAnimation  property: "scale"; from: 1.0; to: 0; duration: 500 
        
    

当我点击第一个项目(项目 1)时,它被删除了,但项目 2 飞到了窗外。 ListView 将剩余项目显示在错误的位置。 ContentY 变为 80(之前是 Item 2 的 y 位置),而不是保持在 0。

qml: onContentHeightChanged: 300
qml: onContentHeightChanged: 240
qml: onContentHeightChanged: 210
qml: remove: 0, contentY:0
qml: onContentYChanged: 80
qml: onContentHeightChanged: 160

如果满足以下条件,它将正常工作:

删除除最上面的其他项目。 禁用部分或动画。

【问题讨论】:

你好。你还需要帮助吗?如果是这样,您能否澄清一下,>删除除最上面的其他项目之外的其他项目应该是不可删除的,究竟是什么意思?如果是这样,如果组中的元素很少,我应该能够删除第一个元素吗? @MaximSkvortsov 当 ListView 中有很多项时,该错误仅在删除第一个(顶部)项时发生。 【参考方案1】:

我使用 Qt 5.13.1 尝试了您的代码。目前正在下载 Qt 5.15。目前看来这是section 的一个错误,因为我在bugtracker 上发现了很多未关闭的错误报告。我可以建议 2 种方法来解决您的问题。

    在解除锁定时执行动画。 使用带有类别的模型。

第一个解决方案我自己测试过。以下是您需要更改才能尝试的内容:

删除 ListView 的移除动画。将以下代码添加到您的委托

ListView.onRemove: SequentialAnimation 
                        PropertyAction  target: wrapper; property: "ListView.delayRemove"; value: true 
                        ParallelAnimation 
                            NumberAnimation  target: wrapper; property: "opacity"; to: 0; duration: 500 
                            NumberAnimation  target: wrapper; property: "scale"; to: 0; duration: 500 
                        
                        PropertyAction  target: wrapper; property: "ListView.delayRemove"; value: false 
                    

这是什么? ListView 有一个信号remove(),在从视图中删除项目之前调用它。它在documentation 中进行了描述,还注意到,

如果已指定删除转换,则在处理此信号后应用它,前提是 delayRemove 为 false。 因此,在委托中,您只需阻止从视图中移除,您是否制作动画并取消阻止它。我想它不会像你想要的那样干净和漂亮,因为在这种情况下视图不只是它的大小。

第二个解决方案

我没有尝试实现它,但我可以想象有这样的模型:

ListModel 
    id: myModel
    ListElement  type: "category"; name: "cat1" 
    ListElement  name: "delegate1"; type: "delegate"; catrgory: "cat1"
    ListElement  name: "delegate2"; type: "delegate"; catrgory: "cat1"
    ListElement  name: "delegate3"; type: "delegate"; catrgory: "cat1"
    ListElement  type: "category"; name: "cat2" 
    ListElement  name: "delegate4"; type: "delegate"; catrgory: "cat2"

要根据需要使用它,您需要相应地对您的委托进行castomize 并相应地删除函数,与section 正常工作相比,这将导致更复杂的代码。

UPD:5.15 中的同样问题

【讨论】:

第一种解决方案对我不起作用,因为我希望同时删除和置换动画,这样看起来更自然。

以上是关于带部分的 ListView,删除动画不适用于顶部项目的主要内容,如果未能解决你的问题,请参考以下文章

onClick 事件不适用于 android 中的嵌套列表视图项控件

Espresso 不适用于 NineOldAndroids 动画?

带约束的 UIImageView 的 iOS 动画

当您一直滚动到 ListView.builder 的顶部时,如何禁用动画

getOptimisticResponse 不适用于带参数的字段

UWP 动画列表项移动