qt - ListView 滚动动画

标签 qt listview animation qml qtquick2

我想为 QML 实现滚动动画 ListView .这是一个示例图像:
ListView scrolling animation
有人可以建议我实现这个吗?

谢谢你。

最佳答案

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)。在这种情况下,一张图片值一千字:

enter image description here
y 之间的区别和 contentY提供可用于计算所需转换因子的值(可能与 heightListView 相关)。确实,正如 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/

相关文章:

javascript - 使用 Divs 类的 setInterval 循环有困难

qt - 在没有指针的情况下在 Qt 中 move 语义?

Android:如何让 Horizo​​ntal-List-View 具有不同宽度的项目?

c++ - QString::fromStdString 崩溃 (c++)

android - 项目之间具有特定间距的 ListView

qt - QML:将滚动条附加到ListView

CSS 反弹动画在 FF 中不起作用

ios - 单个组件的动画打乱了整个 View — SwiftUI

c++ - Qpushbutton 未显示

QML 文本中的 HTML 格式