带部分的 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 动画?
当您一直滚动到 ListView.builder 的顶部时,如何禁用动画