ListView滚动动画

S.M*_*avi 8 animation qt listview qml qtquick2

我想为QML实现滚动动画ListView.这是一个示例图像:
ListView滚动动画
任何人都可以建议我实施这个吗?

谢谢.

BaC*_*Zzo 16

所述ViewTransition提供了大量的关于如何动画一个有趣的例子ListView为象操作populate,(所述在组件创建所述初始项过渡)add,remove(言自明)以及其它操作.

给定一个ListView元素,Transition为每个要设置动画的操作定义一个元素.通过简单地组合基本动画来创建您感兴趣的(或多或少)复杂行为,可以利用动画框架创建复合动画(另请参见此处的实际示例).

这里的定义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 }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,请注意,可以通过使用着色器并在委托的委托/元素上的元素和过渡上组合动画来获取某些行为.一个很好的例子是推文搜索,其中[ShaderEffect][5]条形项的阴影效果(请参阅)与简单Transition打开相结合ListView add.

编辑

在示例中提供自定义滚动需要考虑Items内部的位置ListView.工作解决方案的关键是找到一种方法来计算视图可见部分Item内部的当前位置,并使用该值来计算适当的变换.从中派生出来的有几个有用的属性.ListViewFlickable

但是,该y属性Item是指内容的整体高度ListView.为了使其位置在可见区域的开头,我们可以使用该contentY属性.在这种情况下,一张图片胜过千言万语:

在此输入图像描述

之间的差ycontentY提供了可用于计算所需的值变换因子(可能相对于heightListView).实际上,当ListView被轻弹时,这两个值及其差异会发生变化,从而改变特定的转换因子Item.

这种转变只涵盖部分问题.一旦轻弹/移动结束,Items动画必须"完成"以使所有可见的items可用.为此,我们可以利用Binding及其when属性仅在需要时激活整理动画,即何时flickingdragging结束.

鉴于所有这些(无聊的)介绍,让我们考虑第二个动画(更简单的动画).在这里我们可以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!
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

第一个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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这次我选择(任意)只使用一个Binding.同样可能已经做出了第一个例子,即我们可以写在第一个代表scale: 1 - listY / list.height / 2.

按照类似的方法,您还可以创建第一个动画和其他动画.对于第一个动画,我认为将a Rotation与a 组合Translate就足够了.


S.M*_*avi 11

经过数小时的工作,研究和@BaCaRoZzo的大力帮助(感谢@BaCaRoZzo),我终于找到了正确的解决方案.只需使用Component.onCompleted()事件处理程序来运行与每个委托关联的动画.

这是一个例子,享受!

在QML上滚动动画

import QtQuick 2.3

ListView {
    anchors.fill: parent
    id: list
    model: 100
    cacheBuffer: 50

    delegate: Rectangle {
        id: itemDelegate
        Component.onCompleted: showAnim.start();
        transform: Rotation { id:rt; origin.x: width; origin.y: height; axis { x: 0.3; y: 1; z: 0 } angle: 0}//     <--- I like this one more!
        width: parent.width
        height: 50
        color: index % 2 === 0 ? "#EEE" : "#DDD"
        SequentialAnimation {
            id: showAnim
            running: false
            RotationAnimation { target: rt; from: 180; to: 0; duration: 800; easing.type: Easing.OutBack; property: "angle" }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)