我想为 QML 实现滚动动画 ListView
.这是一个示例图像:
有人可以建议我实现这个吗?
谢谢你。
最佳答案
ViewTransition提供了很多有趣的例子来说明如何为 ListView
设置动画。对于像 populate
这样的操作(组件创建时初始项的转换),add
, remove
(不言自明)以及其他操作。
给定一个 ListView
你定义一个元素Transition
对于您要设置动画的每个操作。 The animation framework可以用来创建复合动画,通过简单地组合基本动画来创建(或多或少)您感兴趣的复杂行为(另见 here 的实际示例)。
这里是 ListView
的定义(第一个链接文档提供了一些漂亮的图片):
ListView {
// data model, delegate, other usual stuff here...
// transitions for insertion/deletation of elements
add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 500 }
NumberAnimation { property: "scale"; easing.type: Easing.OutBounce; from: 0; to: 1.0; duration: 750 }
}
addDisplaced: Transition {
NumberAnimation { properties: "y"; duration: 600; easing.type: Easing.InBack }
}
remove: Transition {
NumberAnimation { property: "scale"; from: 1.0; to: 0; duration: 200 }
NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 200 }
}
removeDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.OutBack }
}
}
最后,请注意,可以通过使用着色器并结合元素上的动画和委托(delegate)/委托(delegate)的元素上的转换来获得一些行为。一个很好的例子是 Tweet Search ,其中条形项目上的阴影效果(参见
[ShaderEffect][5]
)与简单的 Transition
相结合在 ListView
add
.编辑
提供像示例中一样的自定义滚动,需要考虑
Item
的位置在 ListView
内.有效解决方案的关键是找到一种方法来计算 Item
的当前位置。在 View 的可见部分内并使用该值来计算适当的转换。 ListView
源自 Flickable
为此目的,它具有几个有用的属性。但是,
y
Item
的属性(property)是指ListView
内内容的总高度。 .有它的位置 w.r.t.可见区域的开头我们可以使用 contentY
属性(property)。在这种情况下,一张图片值一千字:y
之间的区别和 contentY
提供可用于计算所需转换因子的值(可能与 height
的 ListView
相关)。确实,正如 ListView
轻弹,这两个值及其差异会发生变化,因此会更改特定 Item
的转换因子.这种转变只涵盖了问题的一部分。一旦轻弹/移动结束
Item
s 动画必须“完成”才能使所有可见 item
可用。为此,我们可以利用 Binding
及其when
属性仅在需要时激活结束动画,即当 flicking
或 dragging
结束。鉴于所有这些(无聊的)介绍,让我们考虑第二个动画(更简单的一个)。这里我们可以使用
scale
以获得想要的效果。 delegate
ListView
中的代码如下所示:ListView {
id: list
model: 100
spacing: 10
delegate: Rectangle {
id: itemDelegate
property int listY: y - list.contentY // stores the difference between the two values
width: parent.width
height: 50
border.color: "lightgray"
color: "red"
Binding {
target: itemDelegate
property: "scale"
value: 1 - listY / list.height / 2 // the "scale" property accepts values in the range [0, 1]
when: list.moving || list.flicking || list.dragging // ...when moved around
}
Binding {
target: itemDelegate
property: "scale"
value: 1 // flick finished --> scale to full size!
when: !(list.moving || list.dragging) // not moving or dragging any more
}
Behavior on scale {
NumberAnimation { duration: 100; to: 1}
enabled: !(list.flicking || list.dragging) // active only when flick or dragging ends!
}
}
}
第一个
Binding
根据 listY
定义比例因子而第二个将缩放设置为 1
但仅当 ListView
不动。决赛Behavior
是平滑过渡到完全缩放 Item
所必需的.第三种效果可以通过
Rotation
以类似的方式获得。 :ListView {
anchors.fill: parent
id: list
spacing: 10
model: 100
delegate: Rectangle {
id: itemDelegate
property int listY: y - list.contentY
property real angleZ: (90 * listY) / list.height // 0 - 90 degrees
transform: Rotation { origin.x: width / 2; origin.y: 30; axis { x: 1; y: 0; z: 0 } angle: angleZ}
//transform: Rotation { origin.x: 0; origin.y: 30; axis { x: 1; y: 1; z: 0 } angle: angleZ} <--- I like this one more!
width: parent.width
height: 50
border.color: "lightgray"
color: "red"
Binding {
target: itemDelegate
property: "angleZ"
value: 0
when: !(list.moving || list.dragging)
}
Behavior on angleZ {
NumberAnimation {duration: 200; to: 0}
enabled: !(list.flicking || list.dragging)
}
}
}
这次我选择(任意)只使用一个
Binding
.第一个例子也可以这样做,即我们可以在第一个委托(delegate)中写 scale: 1 - listY / list.height / 2
.按照类似的方法,您还可以创建第一个动画和其他动画。对于第一个动画,我认为结合
Rotation
与 Translate
应该足够了。
关于qt - ListView 滚动动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27078251/