我想在ListView
捕捉到特定项目时为“捕捉”效果设置动画。
我启用了snapMode: ListView.SnapOneItem
属性的“捕捉”。目前它只是减速到当前项目并停止,但如果我能让它在停止时产生“反弹”效果,那就太好了。
关于我如何做到这一点的任何想法?
Flickable
有一个rebound
属性,但这似乎不适用于在ListView
.
由于您使用SnapOneItem
,您可以在移动完成后插入反弹效果,即一旦movementEnded
发出信号。在这种情况下,IMO 对每个项目应用动画将是矫枉过正。更好的做法是contentY
为ListView
.
以下是产生反弹的可能方法(不知道这是否是您正在搜索的确切效果):
ListView {
id: list
anchors.fill: parent
spacing: 10
snapMode: ListView.SnapOneItem
model: 100
delegate: Rectangle {
width: parent.width
height: 50
Text { // added text to distinguish items
text: index
font.pixelSize: 20
anchors.centerIn: parent
}
color: index % 2 ? "lightGray" : "darkGrey"
}
onMovementEnded: {
bounce.start() // starts the animation when the movement ends
}
onCurrentIndexChanged: {
if(!list.moving) // animation started only if the list is not moving
bounce.start()
}
Timer {
repeat: true
interval: 2000 // enough time to let the animation play
running: true
onTriggered: {
list.incrementCurrentIndex()
}
}
SequentialAnimation {
id: bounce
running: false
NumberAnimation {
target: list
property: "contentY"
to: list.contentY - 10
easing {
type: Easing.InOutBack
amplitude: 2.0
period: 0.5
}
duration: 250
}
NumberAnimation {
target: list
property: "contentY"
to: list.contentY
duration: 800
easing {
type: Easing.OutBounce
amplitude: 3.0
period: 0.7
}
}
}
}
当您从拖动或移动中释放项目时,会产生反弹。和属性可以调整以获得更强或更轻的效果(同样适用于属性的值amplitude
)。period
to
如您所见,如果列表通过incrementCurrentIndex()
没有实际移动发生移动,即movementEnded
不会发出信号。在这种情况下,您可以利用currentIndex
. 我已经修改了示例,将这种方法与前一种方法结合起来,并展示了我插入Timer
调用incrementCurrentIndex()
函数的用法。
添加检查是为了避免在!list.moving
移动列表时出现双重动画并保证示例中的一致性,因为在Timer
拖动列表时会产生不一致的跳转。显然,可以根据您的要求添加其他更具体的约束。